【发布时间】:2021-12-01 02:31:14
【问题描述】:
考虑以下代码:
#include <stdio.h>
void foo() {
printf("Hello world\n");
}
void bar() {
printf("Hello world");
}
这两个函数产生的程序集是:
.LC0:
.string "Hello world"
foo():
mov edi, OFFSET FLAT:.LC0
jmp puts
bar():
mov edi, OFFSET FLAT:.LC0
xor eax, eax
jmp printf
现在我知道puts and printf 之间的区别了,但我发现 gcc 能够自省 const char* 并确定是调用 printf 还是 puts,这很有趣。
另一个有趣的事情是,在bar 中,编译器将返回寄存器 (eax) 清零,即使它是一个 void 函数。为什么它在那里而不是在foo 中这样做?
我是否正确假设编译器“内省了我的字符串”,或者对此有另一种解释?
【问题讨论】:
-
顺便说一句:一个好的编译器确实会检查格式字符串,因为它会验证所提供参数的数量和类型,并在不匹配时发出警告。
-
@Gerhardh 编译器需要检查字符串是否存在换行符。
-
@Gerhardh
puts在字符串之后输出一个换行符,因此如果没有,则无法替换。 -
@Gerhard
puts不检查任何东西:它输出你给它的东西,但还有另一个运行时差异。如果我将NULL指针作为字符串传递给printf,MSVC 会友好地(但不是必须)输出(null),但使用puts它会崩溃。 -
这不是对字符串的自省;编译器没有调查自己。这是普通的旧检查。
标签: c gcc assembly compiler-optimization