为什么使用带换行结尾的printf时,nm列出的未定义符号是puts?
问题解答
1. 首先排除宏替换的可能
你可以通过GCC的预处理参数直接验证是否是stdio.h的宏替换导致的:
执行命令 gcc -E ex00/is_alphabet.c 输出预处理完成的代码,搜索对应printf调用的位置,你会发现预处理完成后代码里依旧是printf语句,没有被替换为puts,所以宏替换的假设不成立。
2. 该现象的本质是GCC的内置函数优化
这是GCC默认开启的标准库函数优化特性,目的是降低运行开销、提升执行效率:
GCC对常用标准库函数内置了等价替换逻辑,其中对printf的优化规则就包含:
- 当检测到printf调用同时满足三个条件:格式字符串仅包含
%s+末尾换行符、仅传入一个对应字符串类型的参数、没有使用自定义格式修饰符时,GCC会直接将该调用等价替换为puts调用。 puts的原生功能就是输出字符串后自动追加换行,和printf("%s\n", str)的行为完全一致,且不需要解析复杂格式串,运行开销远低于printf。- 当你去掉格式串末尾的换行符时,
printf("%s", str)的行为和puts不匹配(puts会自动加换行),所以GCC不会触发该优化,会保留原始的printf调用。
3. 如何禁用该优化
如果需要强制保留printf调用,可以在编译时添加-fno-builtin-printf参数,即可关闭printf的内置优化逻辑,此时无论是否带末尾换行,都会生成printf的调用符号。
内容的提问来源于stack exchange,提问作者user16841605
相关产品推荐
相关产品推荐

