在 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
(例如,&x + 1 == &y
可能是偶然为真)。它不会产生未定义的行为。根据标准,许多(但不是全部)无效地址未定义以计算/使用,因此在p == &x
和p
中,或在&x + 2 == &y
中,无效地址会导致未定义的行为,而不是@987654328 @。
另一方面,>=
和其他比较在应用于不指向同一对象内的指针时是未定义的。这包括测试q >= NULL
,其中q
是一个有效的指针。这个测试是我的问题的主题。
我从事低级嵌入式代码的静态分析器工作。这种代码做超出标准允许的事情是正常的。例如,在这种代码中,指针数组可以用memset(...,0,...)
初始化,尽管标准没有规定NULL
和0
必须具有相同的表示。为了有用,分析器必须接受这种东西并以程序员期望的方式解释它们。警告程序员会被视为误报。
所以分析器已经假设NULL
和0
具有相同的表示(您应该根据分析器检查编译器以确保它们同意这种假设)。我注意到一些程序将有效指针与 NULL 与 >=
进行比较(this library 是一个例子)。只要NULL
表示为0
并且指针比较被编译为无符号整数比较,就可以按预期工作。
我只希望分析器警告这一点,也许是因为一些积极的优化,它可能被编译成与程序员在传统平台上的意思不同的东西。因此我的问题是:在NULL
表示为0
的平台上,是否有任何程序没有将q >= NULL
评估为1
的示例?
注意:这个问题不是关于在指针上下文中使用 0 来获取空指针。关于NULL
表示的假设是一个真实的假设,因为memset()
示例中没有转换。
【问题讨论】:
如果您要初始化一个指针数组,为什么不直接使用void *pointers[SIZE] = NULL ;
(默认也将其余指针初始化为NULL
)?
@Chris Lutz 该构造声明并初始化。有时内存已经被保留,你只想初始化。
不知道>= NULL
的意义何在……
@Pascal Cuoq - 哦,好吧。我会使用上面的,然后使用memcpy(dst, pointers, size_of_dst)
,但我认为将这样的事情强加给程序员是不好的,特别是对于嵌入式代码。
@pst 在 QuickLZ 中,比较是在循环中进行的。在第一次迭代中,其中一个指针为 NULL。对于以下迭代,它们都是输出缓冲区内的指针。但它当然可以替换为符合标准的p == NULL || p <= q
。
【参考方案1】:
肯定有一些指针,当您将它们重新解释为指针大小的有符号整数时,它们将带有负号。
尤其是 Win32 上的所有内核内存,如果您使用“大地址感知”,那么甚至 1GB 的用户空间,因为您获得了 3GB 的用户空间。
我不知道 c 指针算法的细节,但我怀疑这些在某些编译器中可能会比较为
【讨论】:
这不太可能,与 /3GB 选项一样,您可能有一个数组跨越内存中间的 2GB 行,如果编译器对指向该数组的指针使用有符号比较,它会是错的。尽管如此,该标准确实允许使用指针的带符号比较的机器,其中一些可能是以上是关于在 NULL 表示为 0 的平台上,编译器是不是曾经为 NULL <= p 生成意外代码的主要内容,如果未能解决你的问题,请参考以下文章