【问题标题】:How compiler handles a non-zero null pointer value in C?编译器如何处理 C 中的非零空指针值?
【发布时间】:2021-02-01 09:16:39
【问题描述】:

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

如果底层架构有一个空指针值定义为地址 0xDEADBEEF,那么就由编译器来解决这个问题。

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

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

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

所以0 是一个空指针常量。如果我们将其转换为指针类型,我们将得到一个空指针,对于某些架构,它可能是非全位为零的。

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

【问题讨论】:

标签: c null compiler-construction literals null-pointer


【解决方案1】:

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”出现在源代码中并不意味着编译器必须在其生成的指令中使用零。它会生成完成工作所需的任何指令和值。

我真的无法理解这个文字 0 在初始化为指针时如何变成非全零位。

字符“0”并没有强迫编译器给它一个零值。 “0”的代码在 ASCII 中是 48,在 EBCDIC 中是 240,因此编译器在处理这个字符或其他字符时不会从零值开始。通常,在处理数字时,它必须读取数字并进行一些算术运算来计算数字所代表的数字。正是那个软件使“0”代表值零或使“23”代表值二十三。为了使“0”表示空指针,编译器中的软件只需将空指针的内部值替换为上下文中使用“0”的指针。

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

【讨论】:

  • 我对您的回答有两个疑问。首先:您的意思是说文字 0 实际上并不代表此特定上下文中的值 0。它将在内部转换为0xDEADBEEF。正确的 ?第二:你为什么用词 character 表示 0 ?在这种情况下,这不是整数常量文字吗?我们为什么要谈论它的 ASCII 值?
  • @LocalHost:源文件由字符组成。编译器必须读取字符并解释它们。在编译器读取源文件中的字符并解释它们之前,不存在整数常量字面量之类的东西。为了让编译器按照我们想要的方式运行,我们只需在编译器中编写软件来按照我们想要的方式解释字符。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多