我知道(char *) 0
是一个char指针,它将地址指向0.所以没有内存地址,超出范围。通常,我看到人们使用它而不是NULL
,所以为什么他们只是简单地使用NULL
?或者,我想知道,是否有任何特殊方法。
答案 0 :(得分:1)
严格来说,null pointer没有有效的地址编码:
值为0的整型常量表达式,或者类型为void *的表达式,称为空指针常量.66)如果将空指针常量转换为指针类型,则生成的指针称为null指针,保证比较不等于指向任何对象或函数的指针。
因此,我试着避免使用短语"地址0"当谈到空指针时,因为这是编码而空指针不需要所有位都为零。例如,架构可以使用指针变量中未使用的位将其标记为无效。比较例如将使用bitops而不是compare。
最常见的编码是"所有位为零",尽管如此,我将主要关注这一点。使用此编码是因为大多数CPU具有特殊(和更短/更快)指令,以将0x0
的位值存储到存储器单元中,并与0x0
的/ test进行比较。使用特殊的bitpattern也可以使用单个比较直接比较两个指针。设置专用位的版本需要额外的指令。
同样位于地址范围边缘的值可避免间隙。对于"所有位1和#34;也是如此,但CPU支持和地址宽度依赖性较小。
请注意,大多数架构都有一个有效的物理地址0
,因此对于空指针,这种编码实际上存在问题地址翻译。幸运的是,这通常是一个特殊的地址,而不是正常的应用程序代码使用。使用虚拟内存寻址,只需使地址0x0
无效,因此无需讨论。
在某些系统上,地址0x0
用于代码(PC启动代码/ BIOS,嵌入式系统)或数据访问(RAM /外围硬件寄存器)。严格地说,你不能将整数常量 0
转换为指针而不调用隐式转换为空指针。因此,如果您的系统不使用0x0
编码,则仅使用标准C语法访问地址0x0
时出现问题。 (仅供参考:这是其他语言为空指针常量使用特殊关键字的一个原因,例如pascal NIL
,Python None
,C ++ nullptr
。)< / p>
无论如何,整数到指针的转换都是实现定义的,空指针编码也是如此。因此,0
到指针的转换与普通的仅复制整数 - >指针编码完全一致,而无需修改表示。
解除引用此类指针时出现问题。取消引用空指针是未定义的行为(UB)。由于两种编码都相同,因此CPU无法检测这是否是有效访问或空指针解除引用。更糟糕的是:如果编译器检测到char c = *((char *)0);
之类的内容,编译器可以自由地利用这个UB并生成任意代码(或者根本不生成代码)。
对于一个真正的变量(即不是const
限定的)指针,这通常不是什么大问题,因为这需要动态代码分析,而在C中,编译器不会生成运行时检查代码,但是对于上面的常量表达,可以很好地导致问题。
答案 1 :(得分:0)
空指针是一个特殊的指针值,已知它不会指向任何地方。这意味着没有其他有效指针,任何其他变量或数组单元格或其他任何东西,将比较等于空指针。
在程序中获取空指针的最简单方法是使用预定义的常量NULL,它由几个标准头文件(包括,和)定义。要初始化指向空指针的指针,可以使用
之类的代码#include <stdio.h>
int *ip = NULL;
并在检查指向您的值之前测试它是否为空指针可能使用
之类的代码if(ip != NULL)
printf("%d\n", *ip);
也可以通过使用常量0来引用空指针,您将看到一些代码通过简单地设置空指针
char *ip = 0;
答案 2 :(得分:0)
简短的回答:你是否说
char *p1 = NULL;
或
char *p2 = (char *)0;
或
char *p3 = 0;
它们都非常相同。它们都是合法的,它们都可以工作,它们都会将指针变量初始化为空指针值。他们之间的差异与风格有关,而不是正确性。
无论是谁编写了你所看到的代码,对于什么构成好的风格都有不同的看法。
(现在,如果你正在处理char *
以外的类型的指针,使用(char *)0
会很差,并且至少应该产生警告,并且在适当的模糊情况下实际上可能会导致问题。 )
答案 3 :(得分:-1)
NULL表示指针不指向任何地址,NULL表示(void *)0
的宏所以你可以使用(char *)0,它仍然会指向什么,并且解释代码会更容易