繁体   English   中英

C 中未初始化指针的值

[英]values of uninitialized pointers in C

假设我们在 C 中有以下声明:

double d[25], * p;
int * t;
char * c;

我们如何解释以下 printf() 结果?

printf("d : %x\t",d);
printf("p : %x\t",p);
printf("t : %x\t",t);
printf("c : %x\t",c);

打印 ligne :

d : 62fd30    p : 1    t : 0    c : 39    

我们可以清晰地看到 d 的内存地址,但 p、t 和 c 看起来都不像地址。 我曾经认为未初始化的指针在声明后采用 Null 值。 我错了吗? 我们如何解释这些结果?

默认情况下,所有自动(非静态局部)变量都将使用不确定的值(可能看起来像随机或垃圾)进行未初始化。 变量是否是指针并不重要。

此外,仅读取未初始化指针的值不会自动 UB(在 C 中),但取消引用未初始化指针肯定是。

但是,正如在一条评论中提到的,您需要使用"%p"来打印指针(从技术上讲,它们也需要转换为void * )。 printf格式说明符和参数类型匹配导致 UB。

您不能假设任何指针在声明后都将被零初始化 - C 标准在这一点上并不暗示任何事情。 其他类型的值也是如此。 这就是为什么在声明时设置变量的值是一个很好的做法,例如:

int * t = NULL;

一些编译器对变量进行零初始化,但这是特定于工具的功能。

我曾经认为未初始化的指针在声明后采用Null值。 我错了吗?

是的,你的假设是不正确的。 自动存储声明的未初始化指针总是包含垃圾或垃圾数据,即不是有效地址,因此最好在声明时首先用NULL初始化。 例如

double *d = NULL;
/* some processing */
if(d == NULL) {
  /* @TODO error handling. Not allowed to de-reference NULL pointer */
}

这里

double d[25];
printf("d : %x\t",d);

d是一个包含25双精度和数组名称本身 address数组,而使用%x打印d会导致未定义的行为,甚至您的编译器也可能会像这样警告您

main.c:5:19: 警告:格式指定类型“unsigned int”但参数类型为“double *”[-Wformat]

但是您似乎忽略了编译器警告,这是不应该的。 始终使用-Wall类的最少标志来编译您的代码。 例如

gcc -Wall -Werror -Wpedantic test.c

要打印数组名称,请使用%p格式说明符。 例如

double d[25];
printf("Array d : %p\t",(void*)d);

int指针tchar指针c类似,使用%p格式说明符而不是%x 也不要在代码中保留任何未初始化的指针。

int * t; /* initialized with valid address else 
            dereferencing uninitialized pointer causes UB */
printf("t : %p\n",(void*)t);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM