声明为int v [100]的数组但是&(v [100])没有给出警告

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指向数组对象的最后一个元素

  • 老实说,引用不回答我的问题.你也说过允许将一个指针移动到一个超过数组最后一个元素的指针(并且引用实际上并不与你所说的相关),但我实际上也是_also_得到了元素的地址.最后一个元素(首先访问它)... (2认同)