变量a在两个单独的函数中声明,但仅在其中一个函数中初始化。 main函数调用声明和初始化a的函数,然后调用第二个函数重新声明该变量而不初始化它。它打印42,即使a在不同的函数范围内初始化,其数据应该在函数完成后被销毁。为什么会这样?
#include <stdio.h>
void foo() {
int a = 42;
}
void bar() {
int a;
printf("%d",a);
}
main() {
foo();
bar();
}
答案 0 :(得分:1)
官方的答案就是这个
void bar() {
int a;
printf("%d",a);
}
调用'Undefined Behavior'。任何事都可能发生。它可以打印一首诗,格式化你的硬盘,打开白宫圣诞树上的灯,......它甚至可以打印42,有些人会告诉你如何在某些情况下发生这种情况。
其他地方你有另一个名为a
的变量的事实是无关紧要的
答案 1 :(得分:0)
哦,这是一个很好的。官方它未定义。但我打赌他们中很多人会打印42,因为a可能会在堆栈上使用相同的内存地址。
因此,它的工作原理是,当一个函数被调用时,程序应返回的PC(程序计数器)的值与参数一起被压入堆栈。在这种情况下,foo和bar都没有参数,所以只有一个指针被压入堆栈(所以说从相对地址0开始总共有4个字节)。
然后当一个函数启动时,它的变量被压入堆栈。在这种情况下,它们都将被推入,每个都是4个字节(总共8个字节,从相对地址4开始)。
这是C / C ++中从其他功能/程序中获取数据的常用方法,否则该功能不允许访问。
答案 2 :(得分:0)
未定义的行为。您正在打印未初始化的变量。 a
中的foo
在概念上与条形码中的a
不同。
虽然UB可以(根据标准)执行@ pm100建议的所有奇怪事情中的任何一个,但在现实世界中它将打印出在某些随机存储器位置或寄存器中发生的任何事情。所以,一个未定义的值。
它会打印42吗?有可能。 a:因为有一个随机的机会,未定义的值是42,b:因为可能内存/寄存器是用foo
写成的42并且没有被其他东西覆盖。
我可以依赖它总是打印42吗? 100%,不!
答案 3 :(得分:0)
未定义的行为!
如果优化已关闭,则观察到的行为是clang和gcc print 42。如果添加-O1,foo函数会有效消失,然后printf会打印一些垃圾。
以下程序显示 a 指向的有效地址在两个函数中都相同
#include <stdio.h>
#include <stdint.h>
void foo();
void bar();
void foo() {
uint8_t a = 255;
uint8_t b = 255;
printf("%p\n",&a);
}
void bar() {
uint16_t a;
printf("%p\n",&a);
printf("%hu\n",a);
}
int main(void) {
foo();
bar();
}
输出
0x7fff54dd259e
0x7fff54dd259e
65535
在这些天气条件下,这是我今天在此机器上观察到的行为。你当然可以观察飞猪,粉红色的大象或Legacy container links的任何方式,同时试图观察上面的代码实际上做了什么。