这个程序的输出是什么?

时间:2009-10-07 10:05:53

标签: c++ c linux unix

当我试图在一个简单的c文件中运行编译并执行此语句时:

main(){ printf("%d");}

在HP上,它给了我64,在AIX上它给了我804359524。

有谁能告诉我这是什么行为。

5 个答案:

答案 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()中修改了相同的寄存器,这就是它失去价值的原因。该死的优化;)