这是一个显示指针地址的简单程序:
#include <stdio.h>
int main(void)
{
int *a;
int *b;
printf ("address of a : %p, the address of b : %p\n", a, b);
return (0);
}
所以输出是这样的:
address of a : 0x7fff537b1ad8, the address of b : 0x0
我的问题是:为什么变量b
的地址存储器无效,而变量a
没有
答案 0 :(得分:1)
两者指针均指向无效内存。仅仅因为指针指向看似有效的内存位置,并不意味着它在程序上下文中有效。
为了详细说明,a
指向的内存位置未分配给您的程序,因此从您的应用程序的角度来看,它是无效的内存。任何读取或写入的尝试都将引起未定义的行为。
换句话说,绝对不能保证b
将保留一个NULL
值,它也可以具有其他看似正确但无效的内存地址。无论它们指向的内存位置如何,它们都是无效的。
答案 1 :(得分:1)
您实际上并不是在打印指针的地址。您正在打印这些指针的值。而且由于这些变量尚未初始化,因此它们的值不确定。
您需要使用address-of运算符获取其地址:
printf("address of a : %p, the address of b : %p\n", (void *)&a, (void *)&b);
请注意,这是需要强制转换为void *
的少数情况之一。
答案 2 :(得分:1)
本地变量具有自动存储持续时间(超出范围,可能分配了堆栈)。
要使用自动存储持续时间(未使用其地址)访问未初始化的变量,则会调用未定义的行为。做任何事情都会发生。
此外,具有自动存储持续时间的未初始化变量具有不确定值。这意味着它可以包含任何值,包括垃圾,零或有效地址。如果您执行两次程序或在程序中读取两次变量,则不需要两次返回相同的值。在某些外来系统上,如果该值是陷阱表示,则访问具有不确定值的变量会导致未定义的行为。
摘要:由于没有C语言或任何其他人的保证,因此无法说明该代码将做什么。对此类代码的作用进行推理是没有意义的。
作为一个补充说明,地址0
与NULL不是同一回事,并且不一定表示空指针。 NULL是空指针常量,不是地址,其值为整数0
或(void*)0
。当将NULL分配给任何类型的指针时,它将创建一个空指针。空指针可以包含任何内部表示形式,例如地址0或其他某个值-C并未指定。
答案 3 :(得分:1)
a
[和b
]从未被初始化,因此它们可以具有 any 值。它们得到的值恰好是在调用main
之前main
堆栈帧的相应存储位置中发生的 。也就是说,a
和b
是 function 作用域变量,因此它们位于函数的堆栈框架中。
在您的情况下,b
得到了0x0,而a
得到了一个非零值,似乎是有效的,但它不是 。它可以指向程序物理地址空间中的任意位置。我们不知道那是哪里。如果我们从中读取,则它可能在程序的分配/有效/映射的地址空间之外,并且我们也会对此进行段错误。
或者,如果我们写入a
所指向的位置,则可能是写入任何位置。因此,我们可能会在随机位置破坏程序数据。这可能不会立即生成异常,但是效果未知。我们可能会覆盖数据段中的值。
这可能会导致程序稍后生成不正确的结果,因为数据段中给定值的值不是静态分配的值。
或者,我们可能破坏了静态分配的 global 内存空间中另一个指针变量中包含的值。稍后,取消引用 指针可能[可能将]产生段错误
它甚至可能指向受保护的内存,例如代码段,这将(再次)生成段错误。