GCC如何处理内置函数

我无法理解GCC内置函数,感到非常困惑。

  • 库函数和内置函数有什么区别?

  • 是否有内置函数可以做但库函数不能做?

  • 我可以编写一个库函数来执行与内置函数printf相同的任务吗? 如何判断输入参数的类型(%f,float还是double)?

  • GCC内置函数的机器指令不存储在库中,对吧? 他们在哪?

  • 在进行链接时,如何控制这些内置function代码的放置位置?

  • 为什么有时我会在进行链接时出现错误消息,例如“未定义引用__builtin_stdarg_start”

    // main.c #include  int main(void) { printf("hello world!\n"); return 0; } 

    gcc -c main.c,nm表明main.o中没有符号printf,(只有main(T)和puts(U)),为什么?

库函数和内置函数有什么区别?

内置函数是编译器直接在编译器本身内部具有一些知识的函数。 库函数只是库中定义的函数。 可能存在内置函数和同名库函数,因此对于其余的问题,我将“库函数”视为“不是内置函数的库函数”。

是否有内置函数可以做但库函数不能做?

是。 例如,内置函数可以选择不评估其参数:

 int main() { int i = 0; __builtin_constant_p (++i); // checks whether ++i is a constant expression // does not evaluate ++i return i; // returns 0 } 

这是因为编译器可以将内置函数转换为其他内容,实际上不需要包含任何函数调用。

我可以编写一个库函数来执行与函数printf相同的任务吗?

有一些内置的printf知识,但在大多数情况下,这是完全可行的。 查找如何使用

如何判断输入参数的类型(%f,float还是double)?

您必须信任调用者让格式字符串与其余参数匹配; 当格式字符串需要double时,你无法检测到传递int这样的东西。 但是你不需要处理floatdouble之间的区别,因为不可能将float传递给printf :它会在printf看到它之前转换为double (不管格式字符串如何)。 printf的要求经过精心设计,以避免任何编译魔术的需要。

GCC内置函数的机器指令不存储在库中,对吧?

对内置函数的调用在编译时进行转换,但该转换可能只是调用同名库函数。

他们在哪?

如果转换在编译时完成,则没有机器指令。 将调用转换为不同的代码,然后编译该代码以生成机器指令。 如果结果是对库函数的调用,则该库函数的机器指令是库的一部分。

在进行链接时,如何控制这些内置函数代码的放置位置?

我不明白你的意思。 对内置函数的调用在编译时转换为不同的代码,然后将不同的代码编译为包含调用的函数的一部分。 它将放在包含函数的其余代码的任何位置。

为什么有时我会在进行链接时出现错误消息,例如“未定义引用__builtin_stdarg_start”

尽管有__builtin前缀,但没有内置函数__builtin_stdarg_start ,因此将其视为对库函数的调用。 并且没有库函数__builtin_stdarg_start ,因此链接器会将此检测为错误。

曾经有一个内置函数__builtin_stdarg_start ,但它在几年前被删除了,代码从来没有应该首先使用它。

gcc -c main.c,nm表明main.o中没有符号printf,(只有main(T)和puts(U)),为什么?

那是因为printf既作为内置函数又作为库函数存在。 内置函数通常只调用库函数,但有时可以做得更好,包括在您的示例中。 在这种情况下,内置函数printf可以在不调用库函数printf情况下提供正确的结果。

内置函数大致有两种:对应于标准库函数的内置函数(默认情况下, mallocprintfstrcpy都被视为内置printf ),而标准库中没有对应函数的内置函数 -想想__builtin_expect__builtin_prefetch等。

第一种内置函数可以使编译器发出优化代码来代替相应的调用。 知道来自标准库的每个调用的内部语义,编译器可以决定发出对驻留在库中的函数的调用,或者在其位置发出自定义生成的代码片段,以便原始语义保留,代码运行得更好。

第二种内置函数(也称为“内在函数”)支持使用驻留在库中的静态代码难以实现的技巧和优化。 它们可以转换为向CPU提供提示( __builtin_prefetch__builtin_expect ),或者通过更好的编译时内省( __builtin_constant_p__builtin_types_compatible_p )来增强C语言,或者为某些特定于体系结构的指令提供更简单的,与平台无关的接口( __builtin_ffs__builtin_popcount )。