在 NULL 表示为 0 的平台上,编译器是不是曾经为 NULL <= p 生成意外代码

Posted

技术标签:

【中文标题】在 NULL 表示为 0 的平台上,编译器是不是曾经为 NULL <= p 生成意外代码【英文标题】:On a platform where NULL is represented as 0, has a compiler ever generated unexpected code for NULL <= p在 NULL 表示为 0 的平台上,编译器是否曾经为 NULL <= p 生成意外代码 【发布时间】:2011-10-26 20:31:45 【问题描述】:

在 C99 中,相等 == 似乎永远不会未定义。如果将其应用于无效地址,它可能会意外生成1(例如,&amp;x + 1 == &amp;y 可能是偶然为真)。它不会产生未定义的行为。根据标准,许多(但不是全部)无效地址未定义以计算/使用,因此在p == &amp;xp 中,或在&amp;x + 2 == &amp;y 中,无效地址会导致未定义的行为,而不是@987654328 @。

另一方面,&gt;= 和其他比较在应用于不指向同一对象内的指针时是未定义的。这包括测试q &gt;= NULL,其中q 是一个有效的指针。这个测试是我的问题的主题。

我从事低级嵌入式代码的静态分析器工作。这种代码做超出标准允许的事情是正常的。例如,在这种代码中,指针数组可以用memset(...,0,...) 初始化,尽管标准没有规定NULL0 必须具有相同的表示。为了有用,分析器必须接受这种东西并以程序员期望的方式解释它们。警告程序员会被视为误报。

所以分析器已经假设NULL0 具有相同的表示(您应该根据分析器检查编译器以确保它们同意这种假设)。我注意到一些程序将有效指针与 NULL 与 &gt;= 进行比较(this library 是一个例子)。只要NULL 表示为0 并且指针比较被编译为无符号整数比较,就可以按预期工作。 我只希望分析器警告这一点,也许是因为一些积极的优化,它可能被编译成与程序员在传统平台上的意思不同的东西。因此我的问题是:在NULL 表示为0 的平台上,是否有任何程序没有将q &gt;= NULL 评估为1 的示例?

注意:这个问题不是关于在指针上下文中使用 0 来获取空指针。关于NULL 表示的假设是一个真实的假设,因为memset() 示例中没有转换。

【问题讨论】:

如果您要初始化一个指针数组,为什么不直接使用void *pointers[SIZE] = NULL ;(默认也将其余指针初始化为NULL)? @Chris Lutz 该构造声明并初始化。有时内存已经被保留,你只想初始化。 不知道&gt;= NULL的意义何在…… @Pascal Cuoq - 哦,好吧。我会使用上面的,然后使用memcpy(dst, pointers, size_of_dst),但我认为将这样的事情强加给程序员是不好的,特别是对于嵌入式代码。 @pst 在 QuickLZ 中,比较是在循环中进行的。在第一次迭代中,其中一个指针为 NULL。对于以下迭代,它们都是输出缓冲区内的指针。但它当然可以替换为符合标准的p == NULL || p &lt;= q 【参考方案1】:

肯定有一些指针,当您将它们重新解释为指针大小的有符号整数时,它们将带有负号。

尤其是 Win32 上的所有内核内存,如果您使用“大地址感知”,那么甚至 1GB 的用户空间,因为您获得了 3GB 的用户空间。

我不知道 c 指针算法的细节,但我怀疑这些在某些编译器中可能会比较为

【讨论】:

这不太可能,与 /3GB 选项一样,您可能有一个数组跨越内存中间的 2GB 行,如果编译器对指向该数组的指针使用有符号比较,它会是错的。尽管如此,该标准确实允许使用指针的带符号比较的机器,其中一些可能是

以上是关于在 NULL 表示为 0 的平台上,编译器是不是曾经为 NULL <= p 生成意外代码的主要内容,如果未能解决你的问题,请参考以下文章

js中的null和undefined

NULL与nullptr

java判断字符串是不是为空

Kafka加Flink不是终点!下一代大数据平台Pravega

java中怎么判断long是不是为"" 或 null

到底是用0表示NULL,还是用NULL表示0