在C中取消引用0的指针

有时,内存地址为0x0的数据非常有价值 – 以x86实模式IVT为例:它从0x0开始,包含指向中断处理程序的指针:0x00处的双字是指向除零error handling程序的指针。

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

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

C不禁止引用空指针,它只是使其不确定的行为。

如果你的环境是这样的,你可以取消引用包含地址0x0的指针,那么你应该可以这样做。 C语言标准没有说明什么时候会发生什么事情。 (在大多数环境中,结果将是程序崩溃。)

一个具体的例子(如果我正确记得这个):在基于68k的Sun 3计算机上,取消引用空指针不会导致陷阱; 相反,操作系统在内存地址为零时存储了一个零值,而取消引用一个空指针(指向地址为零)将产生零值。 这意味着,例如,一个C程序可以将空指针视为一个空string的有效指针。 有些软件,有意或无意,取决于这种行为。 在将软件移植到基于SPARC的Sun 4时,这需要大量的清理工作,而Sun 4则陷入了空指针解引用。 (我清楚地记得关于这个的阅读,但我找不到一个参考,我会更新这个,如果我能find它)。

请注意,空指针不一定是地址零; 更确切地说,空值的表示可能是或者可能不是全零。 它通常是,但不能保证。 (如果不是,那么(void*)0的整数到指针的转换是非平凡的。)

comp.lang.c常见问题的第5部分讨论空指针。

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

通过:

  • 用汇编语言编写所需的代码,或者
  • 用C编写代码并validation它们的编译器为所需的操作生成正确的汇编语言

该声明:

 char * x = 0; 

不一定把0x0放到x中。 它将当前体系结构和编译器的定义的空指针值放入x中。

现在,在实际应用中,所有常用的编译器/处理器都会在寄存器或存储单元中将32位(或64位)0位放在一行中,以响应该语句,因此,如果内存地址0有用,那么正如其他人所指出的那样,你被卡在正式的未定义的行为中。 然而,曾经有硬件在那里,一个“空指针”是一些不全是零的模式,而且谁知道,可能还有一些。

附件J当…时未定义的行为

一元运算符的操作数有一个无效值(6.5.3.2)。

在你提到的那个脚注中,它说空指针是一个无效的值。 所以不是禁止的,而是不确定的行为。 至于地址0x0和空指针之间的区别,请参阅内存地址0x0是否可用? 。

空指针不一定是地址0x0,所以潜在的架构可以select另一个地址来表示空指针,你可以从新获得0x0作为有效地址。

空操作指针是否由操作系统或C ++实现保留是未指定的,但是纯新不会返回空指针,无论它的地址是什么(不是新的是不同的野兽)。 所以,要回答你的问题:

内存地址0x0是否可用?

也许,这取决于特定的实现/体系结构。

换句话说,如果你确信你的系统不会造成崩溃的话,可以随意使用0x0

操作系统使用一个指针表来中断例程来调用适当的中断。 通常(在大多数操作系统中)指针表被存储在低内存( 前几百个位置)中。这些位置保存各种设备的中断服务例程的地址。

所以,当你这样做

 char *ptr = 0x0; 

那么很可能你正在用中断服务程序的地址初始化你的指针。 解引用(或修改)属于操作系统的内存位置极有可能导致程序崩溃。
因此,最好不要初始化一个指向0x0的指针,并将其解引用,直到确认它不属于OS。