以下代码:
char *p1 = 0;
char *p2 = NULL;
char *p3 = (char *)0;
if (NULL == 0)
printf("the NULL is same as 0\n");
printf("0 : %s\n", 0);
printf("p1 : %s\n", p1);
printf("p1 : %x\n", p1);
printf("&p1 : %x\n", &p1);
printf("NULL : %s\n", NULL);
printf("p2 : %s\n", p2);
printf("p2 : %x\n", p2);
printf("&p2 : %x\n", &p2);
printf("*p2 : %s\n", *p2);
输出:
the NULL is same as 0
0 : (null)
p1 : (null)
p1 : 0
&p1 : bf9a0204
NULL : (null)
p2 : (null)
p2 : 0
&p2 : bf9a0208
Segmentation fault (core dumped)
我想知道:
(null)代表什么?
指针p1或p2是否指向地址0x0?
语句printf(“p1:%x \ n”,p1);输出p1:0表示p1指向地址0x0?
答案 0 :(得分:5)
所有这些初始化
char *p1 = 0;
char *p2 = NULL;
char *p3 = (char *)0;
是等价的。所有这些都使用类型为char *
的空指针值初始化这些指针。该空指针值的物理表示是与平台相关的。不保证由物理0x0
地址表示。没有办法说出他们一般会“指向”什么物理地址。
在您的平台上,空指针值恰好由物理地址0x0
表示,由输出判断。但是,使用printf
打印指针值的正确方法是使用%p
格式说明符,或者将指针值转换为合适的整数类型。使用%x
打印指针会导致未定义的行为。
您看到的(null)
输出是printf
对您尝试将%s
说明符与空指针一起使用的反应。这会导致未定义的行为,但您的标准库实现显然决定保存您的命运并打印(null)
。
实际上,代码示例中的每个printf
语句都是错误组合的,每个语句都会导致未定义的行为。
答案 1 :(得分:3)
(null)代表什么?
这是printf()
显然处理传递空指针值时打印字符串的请求的方式。指针值的标准格式说明符为%p
指针p1或p2是否指向地址0x0?
不一定。它们指向您平台上指向空指针的任何内容。
语句printf(“p1:%x \ n”,p1);输出p1:0表示p1指向地址0x0?
不,它只表示转换为时的空指针值作为指针传递给printf(),但重新解释为unsigned int
unsigned int
(这是什么%x期望),结果为零。同样,指针的正确格式说明符是%p
。
答案 2 :(得分:0)
NULL 通常定义为数值0,通常强制转换为指针类型(主要是void *
)。但是,C标准不保证NULL指针为零;有平台(特别是古怪的旧硬件,一些嵌入式系统等),这是另一个非法的内存地址。
但是,您可以使用空指针进行操作,就像它始终为零一样。写作if (pointer)
将转换为if (pointer != NULL)
;此外,当遇到分配或与指针比较的零值时,大多数编译器将其视为一个包含NULL的操作,即使它在技术上不为零。