[英]is there any special approach to using (char *) 0 in C?
我知道(char *) 0
是将地址指向(char *) 0
的char指针。因此,没有超出范围的内存地址。 我经常看到人们使用它而不是NULL
,那么为什么他们不只是使用NULL
? 或者,我想知道是否有任何特殊方法。
空指针严格来说是无效的地址编码:
一个值为0的整数常量表达式,或将这种类型强制转换为void *类型的表达式称为空指针常量。66)如果将空指针常量转换为指针类型,则生成的指针称为空指针。保证比较不等于指向任何对象或函数的指针。
因此,在涉及空指针时 ,我尝试避免使用短语“地址0”,因为这是编码方式,并且空指针不必将所有位都设置为零。 例如,架构可以使用指针变量中未使用的位将其标记为无效。 为了进行比较,例如将使用位运算代替比较。
尽管最常见的编码是“所有位均为零”,所以我将主要集中在此方面。 之所以使用这种编码,是因为大多数CPU都有特殊(且更短/更快)的指令将0x0
的位值存储到存储单元中并与0x0
进行比较/测试。 使用特殊的位模式还可以使用单个比较直接比较两个指针。 设置了专用位的版本将需要其他说明。
此外,位于地址范围边缘的值可避免出现间隙。 “所有位1”也是如此,但CPU支持和地址宽度依赖性较小。
请注意,大多数架构的确有一个有效的物理地址0
,因此对于没有地址转换的空指针 ,这种编码实际上存在问题。 幸运的是,这通常是一个特殊的地址,普通的应用程序代码不使用。 使用虚拟内存寻址时,仅使地址0x0
无效是非常容易的,因此不再讨论。
在某些系统上,地址0x0
用于代码(PC引导代码/ BIOS,嵌入式系统)或数据访问(RAM /外围硬件寄存器)。 严格来说,如果不将隐式转换调用为空指针,就无法将整数常数 0
转换为指针。 因此,如果您的系统不使用0x0
编码,则仅使用标准C语法访问地址0x0
会出现问题。 (仅供参考:这是其他语言为空指针常量使用特殊关键字的原因之一,例如pascal NIL
,Python None
,C ++ nullptr
。)
无论如何,将整数转换为指针都是由实现定义的, 空指针编码也是如此。 因此,从0
到指针的转换与常见的仅复制整数->指针编码完全一致,而无需修改表示形式。
取消引用此类指针时会出现问题。 取消引用空指针是未定义的行为(UB)。 由于两种编码相同,因此CPU无法检测到这是有效访问还是空指针取消引用。 更糟糕的是:如果编译器检测到类似char c = *((char *)0);
东西,则可以自由利用此UB并生成任意代码(或根本不生成任何代码char c = *((char *)0);
。
对于真正的变量(即非const
限定)指针,通常这不是什么大问题,因为这需要动态代码分析,并且在C语言中,编译器不会生成用于运行时检查的代码,但对于上述常量表达式,它很可能会引起问题。
空指针是一种特殊的指针值,已知它不会指向任何地方。 这意味着没有任何其他指向任何变量或数组单元或其他任何有效指针的有效指针将与等于空指针的指针进行比较。
在程序中获取空指针的最直接方法是使用预定义的常量NULL,该常量由几个标准头文件(包括,和)为您定义。 要初始化指向空指针的指针,可以使用如下代码
#include <stdio.h>
int *ip = NULL;
并在检查指向的值之前测试它是否为空指针,可以使用如下代码
if(ip != NULL)
printf("%d\n", *ip);
也可以通过使用常量0来引用空指针,您将看到一些通过简单地设置空指针的代码
char *ip = 0;
NULL表示指针未指向任何地址,NULL是(void *)0的宏
因此您可以使用(char *)0,它仍然指向无内容,并且解释代码会更容易
简短答案:无论您说
char *p1 = NULL;
要么
char *p2 = (char *)0;
要么
char *p3 = 0;
它们几乎相等。 它们全部合法,都可以工作,都将指针变量初始化为空指针值。 它们之间的差异与风格有关,与正确性无关。
无论您写的是谁,看到的代码都可能对好的样式构成有不同的看法。
(现在,如果要处理的char *
类型不是char *
,则使用(char *)0
会很糟糕,并且至少应该生成警告,并且在适当的晦涩环境下可能会引起问题。)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.