无效的指针算术
指针算法的以下用法会导致未定义的行为:
-
如果结果不属于与指针操作数相同的数组对象,则添加或减去整数。 (这里,结尾的元素被认为仍然属于数组。)
int a[10]; int* p1 = &a[5]; int* p2 = p1 + 4; // ok; p2 points to a[9] int* p3 = p1 + 5; // ok; p2 points to one past the end of a int* p4 = p1 + 6; // UB int* p5 = p1 - 5; // ok; p2 points to a[0] int* p6 = p1 - 6; // UB int* p7 = p3 - 5; // ok; p7 points to a[5]
-
如果它们不属于同一个数组对象,则减去两个指针。 (同样,超过结尾的元素被认为属于数组。)例外是可以减去两个空指针,产生 0。
int a[10]; int b[10]; int *p1 = &a[8], *p2 = &a[3]; int d1 = p1 - p2; // yields 5 int *p3 = p1 + 2; // ok; p3 points to one past the end of a int d2 = p3 - p2; // yields 7 int *p4 = &b[0]; int d3 = p4 - p1; // UB
-
如果结果溢出
std::ptrdiff_t
,则减去两个指针。 -
任何指针运算,其中操作数的指针类型与指向的对象的动态类型不匹配(忽略 cv-qualification)。根据标准,“[特别是,当数组包含派生类类型的对象时,指向基类的指针不能用于指针算术。”
struct Base { int x; }; struct Derived : Base { int y; }; Derived a[10]; Base* p1 = &a[1]; // ok Base* p2 = p1 + 1; // UB; p1 points to Derived Base* p3 = p1 - 1; // likewise Base* p4 = &a[2]; // ok auto p5 = p4 - p1; // UB; p4 and p1 point to Derived const Derived* p6 = &a[1]; const Derived* p7 = p6 + 1; // ok; cv-qualifiers don't matter