非同一数组关联指针的比较限制是否适用于C++?遗留代码指针比较合规性问询
C++中指针跨数组/任意void*的比较是否符合标准?
我了解到在C语言(参考Kernighan & Ritchie的《The C Programming Language》第2版102-103页)中,指针只有在指向同一数组的成员时,==、!=、<、>=等关系运算才是合法的;未指向同一数组成员的指针进行算术或比较操作行为是未定义的,唯一例外是数组末尾之后第一个元素的地址可用于算术运算。
现在想请教:这个限制是否同样适用于C++?我们有一些遗留代码会基于绝对地址值比较指针(尤其是
void*),不管它们是否属于同一数组,我担心这些代码是否存在未定义行为,需要重新审视。
好问题!这个点确实很容易混淆,我来帮你理清楚C++里的规则和差异:
1. 指向对象/数组的指针比较规则
和C的核心规则基本一致,但C++在细节上有更明确的定义:
<、>、<=、>=这类关系比较:只有当两个指针指向同一数组的元素(包括数组末尾的哨兵地址),或者指向同一个对象的子对象/成员时,这些操作的行为才是定义良好的。如果是完全无关的对象/数组的指针,用这类操作符比较会触发未定义行为——编译器可能生成不符合你预期的代码,甚至在不同平台表现不一致。==和!=比较:这两个操作符的限制宽松很多。只要两个指针都是有效指针(指向对象/函数/数组末尾哨兵),或者都是空指针,用==/!=判断是否相等都是合法的,结果完全符合预期。哪怕是不同对象的指针,只要地址不同,==就会返回false,这是确定的。
2. 关于void*的特殊情况
void*是C++里的无类型指针,它的比较规则需要单独注意:
==和!=:安全合法。不管两个void*指向的对象是否属于同一数组/对象,只要指针本身有效(或为空),比较结果就是基于地址值是否相同的确定值,没有未定义行为。<、>、<=、>=:风险很高!C++标准明确规定,不同对象/数组的void*使用这类关系比较是未定义行为。哪怕你觉得“地址是整数,比较应该没问题”,但标准不保证这一点——有些平台的内存布局可能导致指针的整数值比较和逻辑地址顺序不一致,或者编译器会做优化破坏你的预期。
3. 针对遗留代码的建议
- 如果你的代码只是用
==或!=比较void*,那通常不用太担心,这类操作是符合标准的。 - 如果代码里有用
<、>等操作符比较无关对象的指针(包括void*),那确实有必要重新审视修改。一个安全的替代方案是把指针转换成uintptr_t(需要包含<cstdint>头文件),然后比较整数——uintptr_t是标准规定可以存储指针地址的整数类型,整数的比较是完全定义良好的,能彻底避免未定义行为。
内容的提问来源于stack exchange,提问作者Sandeep
相关产品推荐
相关产品推荐

