我有以下代码:
#include <stdio.h>
typedef struct {
int* arg1;
int arg2;
} data;
int main(int argc, char** argv) {
data d;
printf("arg1: %p | arg2: %d\n", d.arg1, d.arg2);
}
输出结果是d.arg1
不是NULL
而d.arg2
是0.例如:
arg1: 0x7fff84b3d660 | arg2: 0
当我向main添加指针时,没有任何变化。但是,当我打印指针时:
#include <stdio.h>
typedef struct {
int* arg1;
int arg2;
} data;
int main(int argc, char** argv) {
data d;
int* test;
printf("arg1: %p | arg2: %d | test: %p\n", d.arg1, d.arg2, test);
}
输出总是导致:
arg1: (nil) | arg2: 4195264 | test: (nil)
为什么我会遇到这种行为?我不明白打印另一个指针值如何将不同指针的值更改为NULL。请注意,我使用的编译器是GCC 4.8.2。
答案 0 :(得分:5)
您遇到此行为是因为您的程序调用了未定义的行为。 d
在您的程序中未初始化,因此其值为不确定,这会调用未定义的行为。
C11 6.7.9初始化:
如果没有显式初始化具有自动存储持续时间的对象,则其值是不确定的。
引自this answer:
不确定值比未指定更加未指定。它可以是未指定的值或陷阱表示。陷阱表示是标准 - 代表一些神奇的价值,如果你试图将它分配给任何东西,会导致不确定的行为。这不一定是实际价值;可能最好的思考方式是“如果C有异常,陷阱表示将是一个例外”。例如,如果在块中声明
int i;
而没有初始化,则变量i
的初始值是不确定的,这意味着如果在初始化之前尝试将其分配给其他内容,则行为是未定义的,并且编译器有权尝试所述的恶魔欺骗技巧。当然,在大多数情况下,编译器会做一些不太戏剧性/有趣的事情,比如将其初始化为0或其他一些随机有效值,但无论它做什么,你都无权反对。
答案 1 :(得分:2)
您应该初始化d以获得确定性结果:
data d = {0, 42};
或:
data d;
d.arg1 = 0;
d.arg2 = 42;
如果没有初始化,使用这些值会导致未定义的行为。
答案 2 :(得分:2)
您正在访问未初始化的值。这会导致未定义的行为(意味着任何事情都可能发生,包括程序崩溃)。
要修复,请在使用前初始化值,例如:
data d = { 0 };
答案 3 :(得分:1)
d未初始化,因此它可以包含任何内容。