什么是内在函数?


Answers:


54

通常,“内在函数”是指内置函数,即编译器可以/将生成内联而不是在库中调用实际函数的大多数标准库函数。例如,像这样的调用memset(array1, 10, 0)可以为x86编译为:

 mov ecx, 10
 xor eax, eax
 mov edi, offset FLAT:array1
 rep stosb

这样的内部特性纯粹是一种优化。“需要”内部函数很可能是编译器支持内部函数的情况,这些内部函数可以让您生成编译器无法(或通常不会)直接生成的代码。举一个显而易见的例子,许多x86编译器都具有“ MMX Intrinsics”,可让您使用“功能”,这些功能实际上只是MMX指令的直接表示。


77

内部函数是编译器在可能的情况下直接实现的函数,而不是链接到该函数的库提供的实现。

一个常见的例子是strncpy()

对于短字符串,对进行函数调用strncpy()涉及到使用返回地址设置“堆栈帧”,这将比实际复制字节花费更多的时间。更糟糕的是,对CPU预取缓冲区的影响将使CPU执行停止几个时钟周期。

相反,内部函数由编译器代替函数调用来实现。在的示例中strncpy(),字节复制代码直接在strncpy()调用位置发出。

与此strncpy()示例类似,如果满足所需的约束,则每个内在函数都直接作为内联代码实现。

如果需要函数的地址,则标准库中通常仍存在内部函数的非内部副本。

与内联函数相比,内在函数由编译器提供。C程序的源代码中没有写入内在函数的地方,也没有必须链接的库实现。内联函数的不同之处在于,编译器读取内联函数的源代码,但相似之处在于,稍后它可以将内联函数的编译后的翻译直接发射到目标代码中,从而省去了函数调用的开销。

简而言之,内在函数和内联函数之间的实际区别在于,即使没有#include所需的包含函数声明的头文件,内在函数也“存在” 。对于内联函数,带有函数声明的头文件必须首先是#included(或以其他方式声明)。


9

编译器将内部特性公开为本身不属于任何库的函数。

您可能最常使用的是程序集内在函数,编译器将它们视为它们所代表的机器指令。例如,您将在需要利用编译器不会自动生成的特定CPU指令的代码中使用它们,并且在不一定需要完整的内联汇编节的地方使用它们。


1
用例:SIMD指令集(SSE,Altivec,Neon)在这里编译器很难弄清楚在哪里使用它们,但是寄存器分配/堆栈帧管理的好处仍然可以通过用C编码而不是汇编程序来获得
centaurian_slug

3

“内部特性”是编译器无需程序声明即可识别和实现的语言功能。编译器可以(也可以不)链接到运行时库以执行操作。例如,在C ++中,结构复制操作是隐式的:

struct {
    int  a;
    char b [100];
    long c [27];
} s, t;

...
s = t;   // this statement copies hundreds of bytes, likely with a rtl call

其他示例包括Fortran之类的语言,其中隐含支持复杂类型,并且无需(也不能)声明先验(正弦,切线等)函数。PHP,Javascript,Ruby等具有数百种内部函数,例如创建和搜索数组,执行正则表达式匹配等。

至于您的其他问题,唯一的区别是是否需要声明它们。例如,使用超越函数的C ++程序必须包括数学库声明:

#include <math.h>

没有依赖于内在函数的特定应用程序模式。这对编译器作者和程序员来说只是一个重要的问题。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.