[英]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
指针t
和char
指针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.