编译器如何处理 C 中的非零空指针值?

How compiler handles a non-zero null pointer value in C?

This 回答正确解释了空指针。在 Null Pointers 下的最后一段中说

If the underlying architecture has a null pointer value defined as address 0xDEADBEEF, then it is up to the compiler to sort this mess out.

现在如果某些体系结构在内部将 Null 指针值定义为非零值。这些 if 语句如何有效。编译器如何处理它们?

if (!pointer)
if (pointer == NULL)
if (pointer == 0)

毕竟当一个空指针常量被分配给一个指针时,你得到一个空指针并且空指针常量总是0(void *)0。进一步 回答说

So 0 is a null pointer constant. And if we convert it to a pointer type we will get a null pointer that might be non-all-bits-zero for some architectures.

我真的无法理解这个文字 0 在初始化为指针时如何变成非全位零。这不是一个简单的初始化吗?此外,如果我的空指针值不为零,上述 3 个 if 语句如何检查空指针?我们不是在将非零空指针值与 0 文字进行比较吗?

if (!pointer)

如果 C 实现使用值 DEADBEEF16 作为空指针,编译器会将 if (!pointer) 编译为如下代码:

    compare             pointer, #0xDEADBEEF
    branch-if-not-equal else-clause

if (pointer == 0)

整数常量零符合“空指针常量”的条件 (C 2018 6.3.2.3 3)。将指针与空指针常量进行比较时,空指针常量将转换为指针的类型 (6.5.9 5)。编译器将通过为结果指针生成 DEADBEEF16 来实现此转换。然后它将 pointer 与 DEADBEEF16 进行比较并相应地分支。

简单地说,仅仅因为字符“0”出现在源代码中并不意味着编译器必须在其生成的指令中使用零。它会生成完成工作所需的任何指令和值。

I am really unable to understand how this literal 0 becomes non-all-bits-zero when initialized to a pointer.

字符“0”并没有强制编译器赋予它零值。 “0”的代码在 ASCII 中是 48,在 EBCDIC 中是 240,因此编译器在处理这个或其他字符时不会从零值开始。通常,在处理数字时,它必须读取数字并进行一些运算来计算数字所代表的数字。就是那个软件让“0”代表零值,或者让“23”代表值twenty-three。为了使“0”代表空指针,编译器中的软件只需在上下文中使用“0”作为指针的任何地方替换空指针的内部值。

例如,在 void *x = 0; 中,编译器最初可能会将“0”转换为零,但这将是数据结构的一部分,该数据结构还表示这是一个标记或整数常量表达式,当前具有值为零。当编译器看到这个整数常量表达式被用来初始化一个指针时,它会改变这个值,并且它会生成将指针初始化为空指针的内部值的代码。