避免指针运算的结果溢出
14.5 ID_arrayIndexOverflow
指针运算的结果溢出会导致标准未定义的行为。
设数组元素个数为 N,p 为指向数组第一个元素的指针,i 为整数,标准规定:
- 当 i >= 0 且 i < N 时,p + i 的结果不会溢出
- 当 i 等于 N 时,p + i 的结果不会溢出,但不可对其解引用
- 当 i < 0 或 i > N 时,p + i 的结果可能会溢出
- 使数组下标超出 [0, N] 的运算可能会使指针值溢出,导致未定义的行为
示例:
int a[10]; // 10 elements
int* u = a + 5; // Compliant
int* v = a + 10; // Compliant
int* w = a - 1; // Non-compliant, -1 exceeds [0, 10]
int* x = a + 11; // Non-compliant, 11 exceeds [0, 10]
int* y = &a[0]; // Compliant
int* z = &a[10]; // Compliant in C
C 标准规定,形如 &(E1[E2]) 的表达式等同于 (E1 + E2),C++ 编译器可以兼容 C 标准,但 C++ 标准并无此规定。在 C++ 标准中,E1[E2] 应指代有效的对象或函数,否则程序的行为是未定义的,可参见“CWG issue 232”的最新讨论。
在 C++ 代码中应使用容器代替数组,使用迭代器代替指针,如:
array<int, 10> a;
auto b = a.begin();
auto e = a.end(); // Safe and brief
相关
依据
ISO/IEC 9899:1999 6.5.3.2(3)
ISO/IEC 9899:1999 6.5.6(8)-undefined
ISO/IEC 9899:2011 6.5.3.2(3)
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
参考
MISRA C 2004 17.1
MISRA C 2012 18.1
MISRA C++ 2008 5-0-16
SEI CERT ARR30-C