未指向数组元素的指针不应与整数加减
14.8 ID_illPtrArithmetic
不在同一数组中的地址之间没有连续性,对未指向数组元素的指针进行加减运算往往意味着逻辑错误,也会导致标准未定义的行为。
指向单个对象的指针,以及空指针、未初始化的或已被释放的指针均受本规则约束。
示例:
int *p, i;
p = NULL;
p++; // Non-compliant
p--; // Non-compliant
p = &i;
p -= 1; // Non-compliant, may overflow
p += 1; // Non-compliant
p = &p[2]; // Non-compliant, may overflow
虽然指向单个对象的指针也相当于指向了只有一个元素的数组,但对其值进行增减的实用价值有限,且易导致错误,如增值超过 1,或与非 0 值相减都可能造成指针值溢出,从而导致未定义的行为。
对指向单个对象的指针也不应使用数组下标 [0],如:
p = &i;
p[0] = 1; // Non-compliant
例中 p 指向变量 i,但 p[0] 这种方式会使人误以为 p 指向数组元素。
又如:
struct {
int x, y;
int a[2];
} obj;
assert(&obj.x + 1 == &obj.y); // Non-compliant, no guarantee
assert(&obj.a[0] + 1 == &obj.a[1]); // Compliant, well defined
注意,标准保证排在后面的成员地址大于排在前面的成员地址,但不保证其间是否有填充数据,所以非数组元素的成员之间不应进行指针运算。
相关
依据
ISO/IEC 9899:1999 6.5.6(8)-undefined
ISO/IEC 9899:2011 6.5.6(8)-undefined
ISO/IEC 14882:2003 5.7(5)-undefined
ISO/IEC 14882:2011 5.7(5)-undefined