我写了以下程序:
#include<stdio.h>
int main(){
printf("%x\n");
printf("%x\n");
return 0;
}
我知道这是未定义的行为,我只是检查会发生什么。编译器是gcc。
示例输出为:
541d3118
7ffffff7
另一个示例输出是:
e0b08078
7ffffff7
当我使用-O3
标志编译它时,结果是:
5ec20f18
9
和
3bedfa08
9
为什么第一个值会改变,而不是第二个值?为什么第二个值在高优化级别上有所不同?
答案 0 :(得分:5)
您正在调用printf
而未指定其中包含%x
格式说明符的值。这会调用未定义的行为,因此您观察到的可能是巧合或特定于编译器的实现。无论哪种方式调用未定义的行为都不是代码中的好东西。
答案 1 :(得分:3)
我会从学术角度尝试看你的问题。如你所见,你得到的东西并不可靠(与未定义的行为一样),你永远不应该依赖它。
但是,你有兴趣知道为什么你会看到你所看到的。
本质上,调用函数并将参数传递给它可以通过堆栈工作。 (这仅适用于某些架构,而不适用于所有架构。)
此功能的“常规调用”可能看起来像
push argument 2
push argument 1
call
如果您将其称为
push argument 1
call
该函数将第二个参数看作完全不同的东西,e。 G。返回地址或调用函数的局部变量或当前堆栈中的其他任何内容。
所以这个值取决于之前堆栈上的内容,甚至可能是你所拥有的局部变量和其他情况。
当然,它也可以依赖于所选择的优化级别,因为它控制哪些变量首先放在堆栈上。
这就是为什么你不应该这样做的原因:你绝对无法控制你在这里得到的东西。
答案 2 :(得分:2)
在调用printf
时,根据标准,“如果格式的参数不足,则行为未定义”。你正在目睹这种行为。