首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >GCC是如何处理内置函数的

GCC是如何处理内置函数的
EN

Stack Overflow用户
提问于 2014-05-29 17:56:31
回答 2查看 8K关注 0票数 21

我对理解GCC内置的函数有困难,觉得很困惑。

  • 库函数和内置函数的区别是什么?
  • 是否存在内置函数可以做而库函数不能做的事情?
  • 我是否可以编写一个库函数来执行与内置函数printf相同的任务?如何判断输入参数的类型(%f,float或double)?
  • Machine,GCC内置函数的指令没有存储在库中,对吧?它们在哪里?
  • 在进行链接时,如何控制将这些内置函数代码放在哪里?
  • 为什么在执行链接时有时会出现错误消息,如“未定义的对__builtin_stdarg_start的引用”

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

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

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-05-29 18:23:23

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

内置函数是编译器直接在编译器内部了解的函数。库函数就是在库中定义的函数。一个内置函数和一个同名的库函数可能同时存在,所以对于你剩下的问题,我将“库函数”视为“不是内置函数的库函数”。

有没有内置函数可以做而库函数不能做的事情?

是。例如,内置函数可能选择不计算其参数:

代码语言:javascript
复制
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的内置知识,但在大多数情况下,这是完全可行的。查找如何使用<stdarg.h>

如何判断输入参数的类型(%f、float或double)?

您必须信任调用者让格式字符串与其余参数匹配;当格式字符串需要一个int时,您无法检测到传递double之类的事情。但是您不需要处理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) -c puts(U)),为什么?

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

票数 23
EN

Stack Overflow用户

发布于 2014-05-29 18:45:16

大致有两种类型的内置:一种是对应于标准库函数(默认情况下,mallocprintfstrcpy都被视为内置的),另一种是在标准库中没有对应的--比如__builtin_expect__builtin_prefetch等。

第一种类型的内置是为了使编译器能够发出优化的代码来代替相应的调用。了解来自标准库的每个调用的内部语义后,编译器可以决定发出对驻留在库中的函数的调用,或者发出一段自定义生成的代码来代替它,以便保留原始语义并更好地运行代码。

第二种类型的内置(也称为“内部”)实现了一些技巧和优化,这是驻留在库中的静态代码段很难实现的。它们可以转换为向CPU (__builtin_prefetch__builtin_expect)提供提示,或者通过更好的编译时自省(__builtin_constant_p__builtin_types_compatible_p)来增强C语言,或者为一些特定于体系结构的指令(__builtin_ffs__builtin_popcount)提供一个更简单的、独立于平台的接口。

票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/23930588

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档