有时内存地址为0x0的数据非常有价值 - 将x86实模式IVT作为一个更为人熟知的例子:它从0x0开始并包含指向中断处理程序的指针:0x00处的双字是指向零错误处理程序的指针。
但是,C11语言标准禁止解除引用空指针[WG14 N1570 6.5.3.2],它们被定义为用0初始化的指针或用空指针[WG14 N1570 6.3.2.3初始化的指针,有效地禁止第一个字节。
人们在需要时如何实际使用0x0?
答案 0 :(得分:47)
C不禁止解除引用空指针,它只是使它成为未定义的行为。
如果您的环境是能够取消引用包含地址0x0
的指针,那么您应该能够这样做。 C语言标准没有说明当你这样做会发生什么。 (在大多数环境中,结果将是程序崩溃。)
一个具体的例子(如果我正确记住这一点):在基于68k的Sun 3计算机上,取消引用空指针不会导致陷阱;相反,操作系统在内存地址零处存储零值,并且取消引用空指针(指向地址零)将产生该零值。这意味着,例如,C程序可以将空指针视为指向空字符串的有效指针。有意或无意的某些软件依赖于这种行为。在将软件移植到基于SPARC的Sun 4时需要进行大量的清理,因为Sun 4陷入空指针解引用。 (我清楚地记得读到这个,但我找不到参考;如果我能找到它,我会更新它。)
请注意,空指针不必须为零。更确切地说,null的表示可以是也可以不是全比特零。它很常见,但不能保证。 (如果不是,那么(void*)0
的整数到指针的转换是非常重要的。)
comp.lang.c FAQ的第5节讨论了空指针。
答案 1 :(得分:19)
人们在需要时如何实际使用0x0?
通过以下任一方式:
答案 2 :(得分:9)
声明:
char * x = 0;
不一定将0x0放入x。它将当前体系结构和编译器的已定义空指针值放入x中。
现在,实际上,所有常见的编译器/处理器都会在寄存器或存储位置连续放置32位(或64位)0位以响应该语句,因此,如果内存地址为0然后,正如其他人所指出的那样,你很难使用正式的未定义行为。然而,曾经有一些硬件在那里,“空指针”是一些位模式,不全部为零,并且,谁知道,可能会再次出现。
答案 3 :(得分:2)
附件J ......时是未定义的行为。
一元*运算符的操作数具有无效值(6.5.3.2)。
在您提到的同一个脚注中,它表示空指针是无效值。因此,它不是禁止的,而是未定义的行为。至于地址0x0
和空指针之间的区别,请参阅Is memory address 0x0 usable?。
空指针不一定是地址0x0,所以可能是 架构可以选择另一个地址来表示null 指针,你可以从new获得0x0作为有效地址。
操作系统是否保留空指针 C ++实现未指定,但普通新的永远不会返回 空指针,无论它的地址是什么(nothrow new是一个不同的 兽)。所以,回答你的问题:
内存地址0x0是否可用?
也许,这取决于具体的实现/架构。
换句话说,如果您确定系统不会导致崩溃,请随时使用0x0
。
答案 4 :(得分:2)
操作系统使用指针表来中断例程以调用适当的中断。通常(在大多数操作系统中)指针表存储在低内存中(前几百个左右的位置),这些位置保存各种设备的中断服务程序的地址。
所以当你这样做时
char *ptr = 0x0;
然后很可能是用中断服务程序的地址初始化指针。取消引用(或修改)属于操作系统的内存位置很可能导致程序崩溃
因此,最好不要初始化指向0x0
的指针并取消引用它,直到确认它不属于操作系统。