【问题标题】:void *p...; if (p > 0) .... Is this undefined behavior?无效 *p...; if (p > 0) .... 这是未定义的行为吗?
【发布时间】:2026-01-30 10:10:02
【问题描述】:

我在编译器升级后遇到了一条新的警告消息。

警告:指针与整数零的有序比较 [-Wextra]

    if (inx > 0)

事实证明 inx 是一个指针。通常我希望看到这个旧代码与 0 或 NULL 进行比较。这让我开始思考有符号和无符号值,以及可能的风险。

一些研究表明:

这些似乎表明地址(由 malloc 返回)永远不能为零

这将我带到了我的旧标准副本。

4.10 指针转换

1 空指针常量是整数类型的整数常量表达式 (5.19) prvalue,其计算结果为零 或 std::nullptr_t 类型的纯右值。空指针常量可以转换为指针类型;结果 是该类型的空指针值,并且可以与指向对象或指针的所有其他值区分开来 指向函数类型的指针。这种转换称为空指针转换。的两个空指针值 相同类型应比较相等。将空指针常量转换为指向 cv 限定类型的指针是 单个转换,而不是指针转换后跟限定转换 (4.4) 的序列。 整数类型的空指针常量可以转换为 std::nullptr_t 类型的纯右值。

它明确指出两个空指针比较相等。

考虑到这一点,那一小段代码是未定义的行为吗?还是我错过了另一个难题?

【问题讨论】:

  • 当你if (inx == 0)时你的编译器会告诉你什么?
  • 部分问题在于0 在源代码中 表示的是NULL 指针。但是,NULL 指针可能不会作为 0在内存中存储。它可以是 0xFFFFFFFFFFFFFFFF 或任何其他值。由于 NULL 的 实际 值未指定,因此所有与它的比较也是如此。

标签: c++ pointers


【解决方案1】:

这不是未定义的行为,但如果inx 不为空,则结果未指定。

C++11 5.9/2:如果相同类型的两个指针 p 和 q 指向不同的对象,这些对象不是同一对象的成员或同一数组的元素或不同的函数,或者 if only其中之一为空p<qp>qp<=qp>=q 的结果未指定

因此,您可以确定如果inx 为空,则条件代码不会执行 - 但如果它不为空,则不会执行。比较可能应该是inx != 0,当且仅当inx 不为空时,它才被明确定义为真。

【讨论】:

  • @BenVoigt:我直接从我的 C++11 副本中复制了它。
  • n3690 和 n3797 都有我引用的措辞。那些草案不是包含 C++11 吗?
  • @BenVoigt:我不知道;我只是引用已发布的标准。
  • @BenVoigt:根据*.com/questions/81656/…,您的两个草稿都是 C++11 后的。该措辞出现在 n3290 草案中。
  • @Mat:啊,谢谢。迈克的措辞也在 n3485 中。很好,我们现在已经涵盖了 C++03 和 C++11(在 Mike 的这个答案中)和 C++14。
【解决方案2】:

您正在查看指针转换,但您应该查看指针比较。

具体来说,不引用同一数组或对象(的子对象)的指针之间的比较。

第 5.9 节,第 3 和第 4 段,此措辞可在 C++14 草案中找到。

比较指向对象的指针定义如下:

  • 如果两个指针指向同一数组的不同元素或其子对象,则指向具有较高下标的元素的指针比较大。
  • 如果一个指针指向数组的一个元素或其子对象,而另一个指针指向数组的最后一个元素,则后者的指针比较大。
  • 如果两个指针指向同一对象的不同非静态数据成员,或指向此类成员的子对象,则递归地,如果两个成员具有相同的访问控制,则指向后面声明的成员的指针会比较大(第 11 条)并且他们的班级不是工会。

如果两个操作数 pq 比较相等 (5.10),则 p<=qp>=q 都产生 truep<qp>q 都产生 false。否则,如果指针p 大于指针qp>=qp>qq<=pq<p 都将产生truep<=qp<qq>=pq>p 都产生false否则,每个运算符的结果都是未指定的。

在您的情况下,没有定义“指针比较大于”关系,因此运算符根据其“否则”行为行事,给出未指定的结果。这种比较不会直接使程序崩溃,但它可以通过if 进行任一分支,假设inx 不为空。

【讨论】: