有没有在C中使用(char *)0的特殊方法?

时间:2016-03-25 15:51:38

标签: c

我知道(char *) 0是一个char指针,它将地址指向0.所以没有内存地址,超出范围。通常,我看到人们使用它而不是NULL,所以为什么他们只是简单地使用NULL?或者,我想知道,是否有任何特殊方法。

4 个答案:

答案 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,它仍然会指向什么,并且解释代码会更容易