直接用 std::less 比较不同数组的指针判断重叠是未定义行为;c++ 标准仅允许比较同一数组(或其末尾一格)内的指针。

用 std::less 比较指针来判断重叠是否安全
直接用 或 <code>> 比较两个不同数组的指针是未定义行为(UB),哪怕它们类型相同。C++ 标准只允许对同一数组(或末尾一格)内的指针做大小比较。所以不能写 p1 这类表达式来判断 <code>p2 是否落在 [p1, p1+n1) 内——编译器可能优化掉、运行时结果不可靠。
正确做法是使用 std::less<void></void>,它提供全序(total order),能安全比较任意两个对象指针(包括不同数组):
std::less<void> cmp; bool overlaps = cmp(p1, p2 + n2) && cmp(p2, p1 + n1);</void>
这里 p1, p2 是数组首地址,n1, n2 是元素个数,类型需匹配(如都是 int*)。注意:必须用 void* 特化,std::less<int></int> 不保证跨数组有序。
判断逻辑要覆盖所有重叠情形
两个区间 [a, a+len_a) 和 [b, b+len_b) 重叠 ⇔ 不满足“完全在左”且不满足“完全在右”。即:
- 不重叠当且仅当:
a + len_a (a 完全在 b 左)或 <code>b + len_b (b 完全在 a 左) - 因此重叠条件是:
a
用 std::less 重写就是:
auto cmp = std::less<void>{};
bool overlap = cmp(p1, p2 + n2) && cmp(p2, p1 + n1);</void>
别漏掉任一端点;p1 + n1 是合法的“末尾后一地址”,可参与比较(但不可解引用)。
常见错误:把指针转整数再比较
有人会写 (uintptr_t)p1 ,这看似直观,但有隐患:
- 某些平台(如 Harvard 架构嵌入式系统)中数据指针和代码指针地址空间分离,
uintptr_t可能无法表示全部地址 - 即使能表示,标准不保证转换后整数顺序与对象布局顺序一致(虽然绝大多数通用平台满足)
-
std::less<void></void>是标准规定的唯一可移植、可靠方案
另外,不要用 memcmp(&p1, &p2, sizeof(p1)) —— 这比较的是指针变量自身的内存内容(即地址值),但字节序、填充位可能导致相等指针比较出错。
实际使用时要注意对齐和类型
如果数组是动态分配的(new / malloc),或来自不同栈帧(比如两个局部数组),它们的地址天然不重叠,但代码逻辑仍应统一用上述方式判断,避免误判。
特别注意:
- 确保
p1,p2是有效对象指针(非nullptr,非悬垂);std::less对nullptr的行为是定义良好的,但重叠判断本身无意义 - 若数组元素类型不同(如
int*和char*),先统一转成char*再算字节数:p1 + n1 * sizeof(int)→static_cast<char>(p1) + n1 * sizeof(int)</char> - 对于
std::vector,可用&v[0]获取原始指针,但需确保v.empty() == false
真正容易被忽略的是:这个判断只适用于**已知为连续内存块**的对象(如数组、vector、pod 类型的 buffer)。对 std::deque 或自定义分段容器,地址连续性不成立,这种指针比较毫无意义。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











