当我试图在一个简单的c文件中运行编译并执行此语句时:
main(){ printf("%d");}
在HP上,它给了我64,在AIX上它给了我804359524。
有谁能告诉我这是什么行为。
答案 0 :(得分:21)
我认为你的意思是:
int main()
{
printf("%d");
}
在这种情况下,printf()正在从堆栈中读取int(由格式说明符%d指示)。由于你没有指定一个,它只是读取堆栈中的任何内容并使用它。因此,你看到伪随机输出。
相反,请尝试:
int main()
{
printf("%d", 10101);
}
HTH
答案 1 :(得分:12)
这是经典的undefined behavior。编译器不会检查您是否提供了足够的参数来匹配您的格式化字符串。有编译器执行此操作(gcc is one),但您的编译器没有。
printf()
中的代码将很乐意逐步执行其给定的格式化字符串,当它到达“%d”时,它将读取一个int
大小的参数(通常:来自堆栈) ,不知道那里没有任何争论可供阅读。
无论打印在堆栈上的是什么价值都会打印出来。
答案 2 :(得分:3)
如果指定足够高的警告级别,某些编译器(如gcc)将捕获此类常见问题。像这样(编译代码,使用-Wall - 所有警告):
gcc -c -g -Wall -MMD -MP -MF build/Debug/Cygwin-Windows/newmain.o.d -o build/Debug/Cygwin-Windows/newmain.o newmain.c
newmain.c: In function `main':
newmain.c:16: warning: too few arguments for format
这是始终以高警告级别编译并且认真对待警告消息的大约998个充分理由之一。
答案 3 :(得分:2)
代码暴露未定义的行为。在其他系统上,它可能会打印“Stack Overflow”,(严重!)。 %d告诉CRT库你将提供一个整数,但你没有。
答案 4 :(得分:0)
我的猜测是你编译
main(){ printf("%d");}
这将从当前堆栈中选择一个随机值。试试这个:
main() {
printf("%d", 0);
printf("%d");
}
现在,第二个printf()
将始终打印0
,因为它与第一次调用的堆栈相同。
[编辑]这在使用GCC 4.1.2的x86 Linux上不起作用。这是生成的汇编程序代码(使用gcc -S -o t.s t.c
):
movl $0, %esi
movl $.LC0, %edi
movl $0, %eax
call printf
movl $.LC0, %edi
movl $0, %eax
call printf
如您所见,第二个参数不是在堆栈上推送,而是通过%esi
(这是一个寄存器)传递。可能在printf()
中修改了相同的寄存器,这就是它失去价值的原因。该死的优化;)