谁能解释它们是什么以及为什么我需要它们?如果需要使用内部函数,我将构建哪种应用程序?
Answers:
通常,“内在函数”是指内置函数,即编译器可以/将生成内联而不是在库中调用实际函数的大多数标准库函数。例如,像这样的调用memset(array1, 10, 0)
可以为x86编译为:
mov ecx, 10
xor eax, eax
mov edi, offset FLAT:array1
rep stosb
这样的内部特性纯粹是一种优化。“需要”内部函数很可能是编译器支持内部函数的情况,这些内部函数可以让您生成编译器无法(或通常不会)直接生成的代码。举一个显而易见的例子,许多x86编译器都具有“ MMX Intrinsics”,可让您使用“功能”,这些功能实际上只是MMX指令的直接表示。
内部函数是编译器在可能的情况下直接实现的函数,而不是链接到该函数的库提供的实现。
一个常见的例子是strncpy()
。
对于短字符串,对进行函数调用strncpy()
涉及到使用返回地址设置“堆栈帧”,这将比实际复制字节花费更多的时间。更糟糕的是,对CPU预取缓冲区的影响将使CPU执行停止几个时钟周期。
相反,内部函数由编译器代替函数调用来实现。在的示例中strncpy()
,字节复制代码直接在strncpy()
调用位置发出。
与此strncpy()
示例类似,如果满足所需的约束,则每个内在函数都直接作为内联代码实现。
如果需要函数的地址,则标准库中通常仍存在内部函数的非内部副本。
与内联函数相比,内在函数由编译器提供。C程序的源代码中没有写入内在函数的地方,也没有必须链接的库实现。内联函数的不同之处在于,编译器读取内联函数的源代码,但相似之处在于,稍后它可以将内联函数的编译后的翻译直接发射到目标代码中,从而省去了函数调用的开销。
简而言之,内在函数和内联函数之间的实际区别在于,即使没有#include
所需的包含函数声明的头文件,内在函数也“存在” 。对于内联函数,带有函数声明的头文件必须首先是#include
d(或以其他方式声明)。
编译器将内部特性公开为本身不属于任何库的函数。
您可能最常使用的是程序集内在函数,编译器将它们视为它们所代表的机器指令。例如,您将在需要利用编译器不会自动生成的特定CPU指令的代码中使用它们,并且在不一定需要完整的内联汇编节的地方使用它们。
“内部特性”是编译器无需程序声明即可识别和实现的语言功能。编译器可以(也可以不)链接到运行时库以执行操作。例如,在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>
没有依赖于内在函数的特定应用程序模式。这对编译器作者和程序员来说只是一个重要的问题。