它的输出是什么?为什么?

我正在查看范围规则问题,然后获得一个代码片段,如下所示:

#include  int main() { int x = 1, y = 2, z = 3; printf(" x = %d, y = %d, z = %d \n", x, y, z); { int x = 10; float y = 20; printf(" x = %d, y = %f, z = %d \n", x, y, z); { int z = 100; printf(" x = %d, y = %f, z = %d \n", x, y, z); } } return 0; } 

如果我将最后一次打印更改为:

 printf("x = %d, y = %d, z = %d \n", x, y, z); 

我得到以下输出,我不明白:( Ideone链接)

 x = 10, y = 0, z = 1077149696 

那么,你能解释为什么z打印那个价值吗?

x,y和z被解析为大多数本地定义。

使用不正确的printf%说明符时,行为未定义。

y是浮点数,但您使用%d打印它(在后面的行中)。

printf使用varargs,一旦你通过使用不正确的说明符(在这种情况下%d而不是%f)来破坏堆栈,堆栈就会被破坏并且堆栈数据的错误解释(错误的偏移量)将导致许多痛苦的意外。

解码此UB

这是你的机器上可能发生的事情(一种可能的解释)。 由于默认参数提升 ,位模式(hex) 0x4034000000000000被推送到堆栈20.0f。 您的little-endian机器上的sizeof int是4个字节。 当您将浮点数作为int打印时,您的机器0x00000000被消耗并被解释为int,其首先打印0 ,稍后%d消耗0x40340000将其解释为int并打印1077149696.最终100(0x00000064)保留在堆栈中未消耗并且printf返回。

但是永远不要依赖于此,并始终编写一个行为定义明确的代码。

@ mohit-jain是对的。

使用错误的格式说明符会在堆栈上产生错误的参数解释,从而导致未定义和编译器特定的行为。

请注意,在现代编译器(如gcc或clang)上,它会抱怨您的格式规范错误:

 $ clang test.c test.c:12:54: warning: format specifies type 'int' but the argument has type 'float' [-Wformat] printf(" x = %d, y = %d, z = %d \n", x, y, z); ~~ ^ %f 1 warning generated. 

z = 1077149696
使用%d打印浮点值是未定义的行为。
请改用“%f”

  1. 您使用的所有变量都具有存储类型“自动”或“自动”。
  2. 自动变量的范围位于声明它的块内。
  3. 如果存在嵌套块,则在最外面的块中声明的变量将对所有其他块可见。
  4. 如果块具有声明的变量与外部块中声明的变量匹配,则它将覆盖外部变量“在其块中”即(本地)。

总结:自动变量是声明它们的块的本地变量。