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

gfv*_*gfv 55 c memory pointers dereference

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

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

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

Kei*_*son 47

C不禁止解除引用空指针,它只是使它成为未定义的行为.

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

一个具体的例子(如果我正确记住这一点):在基于68k的Sun 3计算机上,取消引用空指针不会导致陷阱; 相反,操作系统在内存地址零处存储零值,并且取消引用空指针(指向地址零)将产生该零值.这意味着,例如,C程序可以将空指针视为指向空字符串的有效指针.有意或无意的某些软件依赖于这种行为.当将软件移植到基于SPARC的Sun 4时,这需要进行大量的清理,因为Sun 4陷入空指针解除引用.(我清楚地记得读到这个,但我找不到参考;如果我能找到它,我会更新它.)

需要注意的是空指针并不一定是解决零.更确切地说,null的表示可以是也可以不是全比特零.它很常见,但不能保证.(如果不是,那么整数到指针的转换(void*)0是非常重要的.)

comp.lang.c FAQ的第5节讨论了空指针.

  • 实际上这让我想知道,是不是UB都没有为指针分配任意数字并取消引用? (3认同)
  • 定义的@gfv实现是事实上的UB,除非没有恶魔通过鼻子的可能性 (2认同)
  • @MikeWarren:不一定.行为是未定义的,具体意味着,就C标准而言,任何事情都可能发生; "糟糕的时间"不是唯一的可能性.一些系统在地址0处具有可读值0(这导致为这些系统编写的有趣的移植程序到更严格的系统,这些系统捕获了解除引用的空指针). (2认同)

Gre*_*ill 19

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

通过:

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


bma*_*ies 9

该声明:

char * x = 0;
Run Code Online (Sandbox Code Playgroud)

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

现在,实际上,所有常见的编译器/处理器都会在寄存器或存储位置连续放置32位(或64位)0位以响应该语句,因此,如果内存地址0有用,然后,正如其他人所指出的那样,你使用正式的未定义行为.然而,曾经有过硬件,其中"空指针"是一些不是全零的位模式,并且,谁知道,可能会再次出现.

  • @GregHewgill当然,如果不是if(p)会起作用,因为它不会测试0模式,但实际上会测试NULL指针模式的存在(不存在)。 (2认同)