nbr*_*bro 12 c arrays clang undefined-behavior
我有以下程序:
#include <stdio.h>
int main() {
int v[100];
int *p;
for (p = &(v[0]); p != &(v[100]); ++p)
if ((*p = getchar()) == EOF) {
--p;
break;
}
while (p != v)
putchar(*--p);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
这是gcc --version终端上的输出:
Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/usr/include/c++/4.2.1
Apple LLVM version 7.0.2 (clang-700.1.81)
Target: x86_64-apple-darwin15.3.0
Thread model: posix
Run Code Online (Sandbox Code Playgroud)
为什么在数组的最后一个之后获取元素的地址不会给我任何警告但是例如获取地址v[101]会给我以下警告
test.c:8:29: warning: array index 101 is past the end of the array (which
contains 100 elements) [-Warray-bounds]
for(p = &(v[0]); p != &(v[101]); ++p)
^ ~~~
test.c:5:5: note: array 'v' declared here
int v[100];
^
1 warning generated.
Run Code Online (Sandbox Code Playgroud)
我知道缓冲区边界之外的索引元素是未定义的行为,为什么编译器不抱怨第一种情况呢?
Mik*_*CAT 14
除非您取消引用指针,否则允许将指针移动到数组的最后一个元素之外,因此如果在按下EOF之前读取了一个或多个字符,则程序有效.
N1256 6.5.2.1数组下标
下标运算符[]的定义是E1 [E2]与(*((E1)+(E2)))相同.
N1256 6.5.3.2地址和间接运算符
如果操作数是一元*运算符的结果,则不会对该运算符和&运算符进行求值,结果就好像两者都被省略,除了对运算符的约束仍然适用且结果不是左值.类似地,如果操作数是[]运算符的结果,则[]运算符和[]所暗示的一元*都不会被计算,结果就像删除了&运算符并且[]运算符被更改为a +运算符.
N1256 6.5.6加法运算符
此外,如果表达式P指向数组对象的最后一个元素,则表达式(P)+1指向一个超过数组对象的最后一个元素,如果表达式Q指向一个超过数组对象的最后一个元素,表达式(Q)-1指向数组对象的最后一个元素