37622


現在、「独習C++」という書籍を使用しC++を独学で勉強しています。この書籍の中でメモリの動的確保の節の例題プログラム中で、不明点があり質問させて頂きました。以下に例題プログラムを記します。

[code]

    #include "stdafx.h"
    #include "iostream"
    
    using namespace std;
    
    int main()
    {
    int *p;
    
    p = new int[5];     //5つの整数用のメモリを割り当てる
    
    //割り当ての成功を確認
    if (!p) {
        cout << "メモリの割り当てエラー" << endl;
        return 1;
    }
    
    int i;
    
    for (i = 0; i < 5; i++) {
        p[i] = i;          　　　　　　　　　　//※１
    }
    
    for (i = 0; i < 5; i++) {
        cout << "整数型p[" << i << "]は：";
        cout << p[i] << endl;　　　　　　　　 //※２
    }
    
    delete[] p; //メモリの解放
    
    return 0;
    }
    
[/code]

プログラム中の※１,※２で、それぞれ動的に確保したint型ポインタに値の格納と値の表示が行われています。ここで、私が疑問に思っているのはなぜ間接参照演算子＊を使用せずにポインタ変数に値を代入できているのか？p[i]はアドレスを格納する変数なのではないか？ということです。私が思うに、※１の部分は

[code]

    *(p + i) = i;
    
[/code]

※２の部分は

[code]

    cout << *(p + i) << endl;
    
[/code]

と書くべきなのではないかと思います。  
しかし、実際に両方の構文を試してみると、どちらの書き方でもプログラムは正常に動作しました。何故ポインタ変数に直接的に値を格納するような書き方（p[i] =
i;）ができるのか。これをどのように解釈すればよいか悩んでいます。初歩的な質問ですが、ご回答いただければ幸いです。  
よろしくお願いいたします。


CC BY-SA 3.0
2017-08-30T14:08:05.400
37620
2017-08-30T16:02:37.453
25114
question
c++ ポインタ
C++でのポインタから値へのアクセス方法についての質問です。


> 6.5.2.1 Array subscripting  
>  ...  
>  2 A postfix expression followed by an expression in square brackets [] is a
> subscripted  
>  designation of an element of an array object. The definition of the
> subscript operator []  
>  is that E1[E2] is identical to (*((E1)+(E2))). Because of the conversion
> rules that  
>  apply to the binary + operator, if E1 is an array object (equivalently, a
> pointer to the  
>  initial element of an array object) and E2 is an integer, E1[E2] designates
> the E2-th  
>  element of E1 (counting from zero).

`p[i]`は`*(p + i)`のシンタックスシュガーで、まったく同じ意味になります。`i[p]`と書いても同じ意味になります。

[code]

    #include <stdio.h>
    
    int main(void) {
      int a[3] = { 10, 20, 30 };
      printf("a[0] = %d\n", a[0]);
      printf("a[1] = %d\n", 1[a]);
      printf("a[2] = %d\n", *(2 + a));
      return 0;
    }
    
[/code]

つまり、上記のコードを実行すると次のような出力になります。

[code]

    a[0] = 10
    a[1] = 20
    a[2] = 30
    
[/code]


CC BY-SA 3.0
2017-08-30T14:37:06.997
37622
2017-08-30T14:37:06.997
5519
37620
answer


実は`*(p + i)`は、`p[i]`と全く同じ意味なのです。例えば、`*(p + 1)`を`*(1 +
p)`と書けるように、`p[1]`も`1[p]`と書けます (あくまで文法的な話で、現実的には、このように書くメリットはないと思いますが)。

では、配列はどうなのかというと、例えば

[code]

    int a[10];
    a[1] = 10; // (1)
    
[/code]

(1)のところで使われている`a`は、配列の先頭の要素のアドレス、つまり`int`のデータを指すアドレスを返すことになっています。一方、ポインタの場合は

[code]

    int *p = new int[10];
    *(p + 1) = 10; // (2)
    
[/code]

`p`は`int`のポインタですので、当然`int`を指すアドレスが入っています。つまり(1)も(2)も、`int`データを指すアドレスに 1
を足して中身を参照するという、式として全く同じことをしていることになります。

配列でもポインタでも実は同じなので、`*(p + i)`は、`p[i]`と全く同じ意味になっているわけです。


CC BY-SA 3.0
2017-08-30T14:47:02.967
37624
2017-08-30T14:47:02.967
3605
37620
answer


妥当な疑問です。配列は暗黙的にポインタに変換され、`p[i]` に対する代入と `*(p + i)` に対する代入は同じ意味になります。`p[i]`
は「配列 `p` の `i` 番目の値」であり、`*(p + i)` は「`(p + i)` が参照する場所の値」であることに注意してください。

たとえばポインタ `p` へ確保した配列を箱の絵で表すとすると、下のような絵が描けます。

[code]

              +---+---+---+---+---+
    int[5]    |   |   |   |   |   |   配列
              +---+---+---+---+---+
                ^           ^
                |           |
                |           |
                |           |
    int*        | p+0       | p+3     ポインタ
    
[/code]

(上の ASCII アートは
[fredoverflow](https://stackoverflow.com/users/252000/fredoverflow)
さんの[投稿](https://stackoverflow.com/a/4810668/5989200)を参考にしました)

参考

  * [How do I use arrays in C++?](https://stackoverflow.com/a/4810668/5989200) \-- 本家 Stack Overflow
  * [Pointers to arrays](http://www.cplusplus.com/doc/tutorial/pointers/#arrays) \-- CPlusPlus.com チュートリアル


CC BY-SA 3.0
2017-08-30T14:51:52.017
37625
2017-08-30T16:02:37.453
2017-08-30T16:02:37.453
19110
19110
37620
answer