在C中取消引用指向0的指针

时间:2014-01-14 01:42:53

标签: c pointers memory dereference

有时内存地址为0x0的数据非常有价值 - 将x86实模式IVT作为一个更为人熟知的例子:它从0x0开始并包含指向中断处理程序的指针:0x00处的双字是指向零错误处理程序的指针。

但是,C11语言标准禁止解除引用空指针[WG14 N1570 6.5.3.2],它们被定义为用0初始化的指针或用空指针[WG14 N1570 6.3.2.3初始化的指针,有效地禁止第一个字节。

人们在需要时如何实际使用0x0?

5 个答案:

答案 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?

通过以下任一方式:

  • 用汇编语言编写所需的代码,或
  • 在C中编写代码并验证其编译器为所需操作生成正确的汇编语言

答案 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的指针并取消引用它,直到确认它不属于操作系统。