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