代码之家  ›  专栏  ›  技术社区  ›  fredoverflow

我可以取数组结束元素后的地址吗[[副本]

  •  15
  • fredoverflow  · 技术社区  · 15 年前


    Take the address of a one-past-the-end array element via subscript: legal by the C++ Standard or not?

    int array[10];
    
    int* a = array + 10;   // well-defined
    int* b = &array[10];   // not sure...
    

    最后一行是否有效?

    5 回复  |  直到 8 年前
        1
  •  24
  •   Jerry Coffin    15 年前

    是的,可以将地址移到数组末尾之外,但不能取消对它的引用。对于10个项目的数组, array+10 会有用的。有几次(由委员会等)争论是否 &array[10] 是否真的会导致未定义的行为(如果会,是否真的应该)。它的底线是,至少根据当前标准(C和C++),它正式导致未定义的行为,但是如果有一个编译器实际上不起作用,任何参数中的任何人都找不到或引用它。

    编辑:这一次,我的记忆有一半是正确的——这是一个官员的记忆 Defect Report 至少有一些委员会成员(如汤姆·普卢姆)认为措辞已经改变了,这样就可以了

        2
  •  10
  •   Michael Burr    15 年前

    array[10] 相当于 *(array + 10) ,这似乎会导致元素的未定义解引用刚好超过数组的结尾。但是,表达式 &array[10] 相当于 &*(array + 10)

    一元;运算符返回其操作数的地址。如果操作数的类型为type,则结果的类型指针指向type。如果操作数是一元数的结果 * [] 接线员 & 运算符或一元数 这就是 [] 结果是 & 运算符已更改为+运算符。

    所以,没有什么不确定的 & -没有发生解引用操作。

        3
  •  2
  •   Cogwheel    15 年前

    array[10] *(array + 10) (也相当于 10[array] ),所以 &array[10] * *(array+10) . 任何好的编译器都应该发出相同的代码(和相同的警告)。

        4
  •  1
  •   Edward Strange    15 年前

    不,没有定义。 array[10] *(array + 10) . 换句话说,您取消了对无效指针的引用。

        5
  •  -2
  •   Kaiden Prince Elf King    9 年前

    foo.cc地址:

    #include <iostream>
    
    using namespace std;
    int main() {
            int array[10];
            int *a = array + 10;
            int *b = &array[10];
            int *c = &array[3000];
    
            cerr << "Pointers values are: " << a << " " << b << " " << c << endl;
            return 0;
    }
    

    要编译:

    g++ -Werror -Wall foo.cc -o foo
    

    不应产生任何警告,因为int*b=&数组[10]有效

    foo不仅可以编译,而且可以顺利运行:

     ./foo
      Pointers are: 0x7fff1d356e68 0x7fff1d356e68 0x7fff1d359d20
    

    基本上,数组语法foo[idx]是指针数学的简洁明了的表示。

    C99也是这样:

    #include <stdio.h>
    
    int main() {
            int array[10];
            int *a = array + 10;
            int *b = &array[10];
            int *c = &array[3000];
    
            fprintf(stderr, "Pointers are: %p, %p, %p\n" , a , b , c );
            return 0;
    }
    

    然后:

    gcc -std=c99 -Wall -Werror -o foo foo.c
    
    ./foo
    

    Pointers are: 0x7fff2c7d22c8, 0x7fff2c7d22c8, 0x7fff2c7d5180