C++;减去指针时的未定义行为 从非数组元素中减去指针的C++标准是UB:< /P> int a, b; &a - &b; // UB, since pointers don't point to the same array.

C++;减去指针时的未定义行为 从非数组元素中减去指针的C++标准是UB:< /P> int a, b; &a - &b; // UB, since pointers don't point to the same array.,c++,C++,但如果两个指针都被强制转换为uintptr_t,那么这两个表达式就不再是指针表达式,从标准的角度来看,减去它们似乎是合法的: int a, b; reinterpret_cast<uintptr_t>(&a) - reinterpret_cast<uintptr_t>(&b); inta,b; 重新解释演员表(&a)-重新解释演员表(&b); 这是正确的还是我遗漏了什么?从行为不是未定义的意义上讲,整数的减法是合法的 但是该标准在技术上没有保证转换后

但如果两个指针都被强制转换为uintptr_t,那么这两个表达式就不再是指针表达式,从标准的角度来看,减去它们似乎是合法的:

int a, b;
reinterpret_cast<uintptr_t>(&a) - reinterpret_cast<uintptr_t>(&b); 
inta,b;
重新解释演员表(&a)-重新解释演员表(&b);

这是正确的还是我遗漏了什么?

从行为不是未定义的意义上讲,整数的减法是合法的

但是该标准在技术上没有保证转换后的整数的值,因此您也没有保证减法结果的值(除了与未指定的整数值相关的值),您可以得到一个大值或一个小值(或者,如果指针具有不可相互转换的类型,那么对不同对象的已转换整数进行减法运算甚至可能得到零),具体取决于系统


此外,如果您做了一些其他的指针算法,将产生一个指针值,即将指针转换为整数并添加偏移量,那么从技术上来说,无法保证将加法结果转换回指针类型将产生该偏移量处的指针值。但这可能会起作用(假设该地址实际存在正确类型的对象)除非是在使用分段内存或其他更奇特的系统上。

UB允许实现执行任何操作。它不会阻止实现简单地计算地址值之间的差异并除以大小。但它允许实现控制两个元素是否为同一数组的成员(或指向数组的一端)引发异常或崩溃

要求两个指针指向同一个数组允许实现假设这两个指针之间的任何值(并正确对齐…)也是有效的,并且指向同一数组内。

您是正确的

未定义减去不指向同一数组元素的指针的行为。为此,允许指针超出数组的最后一个元素,并且对象作为长度为1的数组计数

但是,一旦您将指针投射到一个合适的类型,例如指向一个
std::uintpttr\t
(假设您的编译器支持它;它不一定支持),您就可以根据该类型对您施加的约束,对其应用任何您想要的算法


尽管这些规则看起来很迟钝,但它们与一个类似的规则有关,即不允许读取不指向有效内存的指针。所有这些都有助于提高语言的可移植性。

您得到一个整数,其值完全由实现定义,因此您不能过多依赖它。这似乎不是很重要尽管取消了UB,但仍然很有用。完全同意@StoryTeller UnslanderMonica。只是想就围绕一个可能类似主题的更多讨论给出一个提示,询问如何迭代结构的成员。请注意,
uintpttr\u t
是可选的。您的实现可能不会提供它。我认为零差异不会是有效的OP的特定情况下的id。将整数值强制转换回指针必须产生原始指针值,如果两个整数值表示形式相同,则两个指针值在类型上也需要相同,但它们的类型相同,因此无法工作。实际上,该标准确实对凸性做出了一些保证rted整数:指针可以转换为任何足够大的整数类型,以容纳其类型的所有值。任何此类值都可以转换回同一指针。(但无法保证指针将转换为哪个整数。例如,您可以将指针转换为整数并返回,然后得到开始时的值,但不能将整数转换为指针并返回,然后保证得到与开始时相同的整数。)(*我不是语言律师。)@walnut您可能是对的。虽然没有明确说明,但在本例中整数不可能具有相同的值。我试图传达的是,即使是相同的地址,不指向相同的对象也不足以使转换后的值不同。但鉴于指针类型相同(因此可相互转换),整数值在实践中必须不同。我更改了措辞。据我所知,第二个代码段中没有UB。@比基涅夫:第二个代码段中没有指针减法。每个指针都转换为int,代码只减法int,因此不涉及UB。但无法保证所有内存在两个地址之间,程序可用。