我现在正在学习C,而这些天我正在学习指针,我只是提出一个问题!
int *ptr; //declare the ptr
ptr = &var; //init the ptr with the address of the variable var
通过这些行,我创建了一个指针,并将 ptr 与一个变量链接起来。我的问题是,当我声明一个指针int *ptr;
并且我没有用地址初始化它时,这个指针指向哪里?
它就像任何其他未初始化的局部变量一样——它指向的位置或包含的值是未定义的,并且在初始化之前不允许使用它(例如,取消引用它)。正如@WhozCraig 的评论中所述,几乎所有其他操作也被禁止(完全使用指针的值,包括算术和比较)。未初始化的非指针变量(即使是像int
s 这样的简单类型)也不能用于任何访问其值的操作。
在 C 中,变量通常不会被初始化,除非你特别说明:
int a; // not initialized
int b = 1; // initialized
int arr[10]; // not initialized
int brr[4] = { 1 }; // initialized as { 1, 0, 0, 0 }
void * p; // not initialized
void * q = &a; // initialized
(具有静态或线程本地存储的变量有例外,它们总是零初始化。)
不允许尝试获取未初始化变量的值。对未初始化的变量唯一能做的就是给它赋值,它不会访问它的当前值,而只会给它分配一个新值。在初始化或赋值之前,变量的当前值是“不确定的”,您不能尝试访问它。这样做会导致未定义的行为。
这适用于所有变量,但尤其适用于您的指针变量。在您分配一个之前,它根本没有有意义的价值。
void * p; // not initialized
if (p) { /*...*/ } // undefined behaviour!
printf("%p\n", p); // undefined behaviour!
p = &a; // now p has a well-defined value
导致未定义行为的操作的技术术语是所谓的“左值转换”。那是您获取命名变量(“左值”)并使用其内容的时刻。例如 C11, 6.3.2.1/2 说:
如果左值指定了一个具有自动存储持续时间的对象 [...] 并且该对象未初始化(未使用初始化程序声明并且在使用之前未对其执行任何分配),则行为未定义。
实际上,正如迄今为止几乎所有答案中所述,指针的值是未知的,并且由分配时该位置的内存内容组成。
与某些答案的状态相反,没有人会禁止您取消引用它,或使用此指针进行任何类型的操作。
结果,使用这样的指针会产生任何一种不可预知的结果。这不仅是最佳实践,而且是生成更少错误代码的要求,在声明中初始化指向某事物的指针,即使该事物简单地为 NULL。
它指向一个随机内存位置。取消引用这样的指针通常会导致段错误。
在这种情况下,它将指向任何地方。你不知道。指针的内容将是之前在内存位置的任何内容。所以这是非常危险的,应该避免。您应该始终使用 NULL 初始化一个指针,然后它将以定义的方式指向“无”。
与 C 中的任何其他非静态变量一样,它不会自动初始化。它包含内存插槽中的任何垃圾数据,因此在为其分配适当值之前对其进行延迟可能是一个坏主意。