Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/azure/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 这个程序的输出是什么?_C++_C_Linux_Unix - Fatal编程技术网

C++ 这个程序的输出是什么?

C++ 这个程序的输出是什么?,c++,c,linux,unix,C++,C,Linux,Unix,当我试图在一个简单的c文件中运行compile并执行此语句时: main(){ printf("%d");} 在HP上是64,在AIX上是804359524 谁能告诉我这是什么行为。代码公开了未定义的行为。在其他系统上,它可能会打印“堆栈溢出”(严重!)。%d告诉CRT库您将提供一个整数,但您不提供。我想您的意思是: int main() { printf("%d"); } 在这种情况下,printf()正在从堆栈中读取int(按照格式说明符%d的指示)。因为您没有指定一个,所以它只是读

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

main(){ printf("%d");}
在HP上是64,在AIX上是804359524


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

代码公开了未定义的行为。在其他系统上,它可能会打印“堆栈溢出”(严重!)。%d告诉CRT库您将提供一个整数,但您不提供。

我想您的意思是:

int main()
{
  printf("%d");
}
在这种情况下,printf()正在从堆栈中读取int(按照格式说明符%d的指示)。因为您没有指定一个,所以它只是读取堆栈上的任何内容并使用它。因此,您可以看到伪随机输出

相反,请尝试:

int main()
{
  printf("%d", 10101);
}

HTH

我猜是您编译了

main(){ printf("%d");}
这将从当前堆栈中拾取一个随机值。试试这个:

main() {
   printf("%d", 0);
   printf("%d");
}
现在,第二个
printf()
将始终打印
0
,因为它与第一个调用具有相同的堆栈

[编辑]这在带有GCC 4.1.2的x86 Linux上不起作用。下面是生成的汇编代码(使用
gcc-S-o t.S t.c
):

如您所见,第二个参数不是推送到堆栈上,而是通过
%esi
(这是一个寄存器)传递的。同一个寄存器可能在
printf()
中被修改,这就是它丢失其值的原因。该死的优化;)

这是经典之作。编译器不会检查您是否提供了足够的参数来匹配格式化字符串。有些编译器可以做到这一点(),但您的编译器却没有

printf()
中的代码将愉快地逐步遍历其给定的格式字符串,当它到达“%d”时,它将读取一个
int
大小的参数(通常是:从堆栈中读取),而不知道那里没有可读取的参数


堆栈上的任何值都会被打印。

某些编译器(如gcc)会捕获此类常见问题,如果您指定足够高的警告级别。如下所示(编译代码时,使用-Wall-all警告):


这是大约998个始终使用高警告级别编译并认真对待警告消息的好理由之一。

我认为在该代码中不会出现堆栈溢出-堆栈没有增长。堆栈溢出的触发器通常是对堆栈保护页的内存访问。printf()在读取%d整数失败时,可能会触发该访问,而不是访问保护页。因为它不是一个书写,你不能通过添加另一个页面来解决它。只要存在任何不可扩展的堆栈保护页冲突,操作系统就可以打印“堆栈溢出”;它将是99%正确的,我认为在这种情况下,打印的值将是printf函数的返回地址、寄存器值或main堆栈帧中的某个值,具体取决于编译器的实现及其运行的操作系统。我一直认为“堆栈溢出”是指在尝试在堆栈上存储数据时堆栈内存不足,而不是在读取数据时。skizz是正确的,不太可能产生堆栈溢出(更可能是返回地址)。但这是一个很大的假设。不是一个大的假设,问题是C和C++的标记。如果你得到1,我不会感到惊讶。printf返回使用的参数数。这个返回值可能会覆盖堆栈。我怀疑有两个原因:a)在大多数机器上,返回值在寄存器中;b)如果它在堆栈上传递,如果它没有被ABI.Aaron保存在其他位置,它会覆盖格式字符串,使用“英特尔icc编译器”运行该命令将发出关于第二个printf的警告,并输出04204818(0和4204818)@Glen:Odd。第二个printf()应该使用与第一个相同的堆栈地址,我认为没有理由覆盖第二个参数:/n您是否有“mungwall”选项处于活动状态,或者有什么东西会破坏未使用的内存?@AAron,没有启用任何特殊选项。“>icc x.cc”,其中x.cc仅包含上述代码。
    movl    $0, %esi
    movl    $.LC0, %edi
    movl    $0, %eax
    call    printf
    movl    $.LC0, %edi
    movl    $0, %eax
    call    printf
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