C语言指针问题 下面代码为什么第二个数字是5呢?
int a[5] = {1,2,3,4,5};
int *p = (int *)(&a+1);
NSLog(@"%d,%d", *(a+1), *(p-1));
阿神2017-04-21 11:19:34
&aは配列へのポインタとして出てくるので、&a+1は実際には配列の長さに基づいて移動します。配列の 2 番目の要素だけを取得したい場合は、*(&a[0]+1) を使用します。これは、&a[0] のデータ型が int* であるためです。最初に絵を描きます。
次の配列があるとします
リーリー上記のプログラムはコンパイルして渡すことはできますが、x と a の型が一致しないため、コンパイラーは警告を出します
警告を解除するには 2 つの方法があります。1. 強制型変換による
リーリー2. 適切な型を見つけます。&a の型は int (*)[5]
です。 リーリーこれには、適切なデータ型の書き方が含まれます。これは、代入とパラメーターの受け渡しにおいて非常に重要です。
それでは、まず a、&a、&a[0] のデータ型を要約する必要があります
a は配列の名前であり、配列の最初の要素へのポインターです ここで、配列の最初の要素のデータ型は int であるため、a のデータ型は間違いありません。は int* です。
&a は 1 次元配列のアドレスを受け取り、その結果は配列へのポインタ (この場合、int の配列へのポインタ)、つまり int(*)[5] になります。
&a[0] は非常に単純です。まず、a[0] は整数を取得し、そのアドレスを取得するため、そのデータ型は int* です。
データ型がわかったので、ポインターの演算がより明確になります。
まず、強制的な型変換を通過するコードの部分を見てみましょう。出力される数値は何でしょうか?
答えは5です! 先ほどのデータ型の概要から、&a のデータ型は int (*)[5] であることがわかります。そのため、&a+1 は実際には 5*sizeof(int) バイト移動されたことになります。 これで、ポインタは配列の最後の要素の後の要素を指します (図 1)。つまり、境界を越えています。ただし、x のデータ型は実際には int * であるため、 したがって、x-1 の場合、実際には 1*sizeof(int) バイト左に移動します。これは、最後の要素を指すことを意味するため、*(x-1) が取得されます。 値は配列の最後の要素です: 5
それでは、2 番目の部分を見てみましょう。どのような数値が出力されるでしょうか。答えについては先に述べたのでやめておきます。 データ型は、 sizeof(int)*5 バイト単位で移動するので、実際には x-1 が sizeof(int)*5 バイトだけ左に移動します。 20 バイト、つまり配列の最初の要素に戻ることを意味するため、答えは次のようになります: 1 上記は 1 次元配列ですが、次に 2 次元配列の場合について説明します。
リーリーまず、a、a[0]、&a、&a[0]、&a[0][0] のデータ型を見てみましょう:
上記の太字のテキストに注目してください。配列名は配列の最初の要素へのポインターです!
a のデータ型は何ですか? ? int *?いいえ、この太字のテキストの核心は 5 つの単語最初の要素です。 a の最初の要素は単なる a[0][0] ではないでしょうか?厳密に言えば、いいえ、a の最初の要素は実際には a[0] です。では、a[0] のデータ型は何でしょうか? [0] は 3 つの int 要素を含む配列であるため、最初の要素のデータ型は であるため、a[0] の型は int t[3] の t の型と同じになります。 int* は、この 2 次元配列を 1 次元配列とみなした場合、実際には 3 つの int* 要素を含む配列になります。 配列はポインターの配列であるため、 a のデータ型は int (*)[3] です。
t のデータ型は同じです (int*)。当然、&a[0] のデータ型は &t のデータ型、つまり int (*)[3] です。
以下のコードを見てください:
リーリー
であるため、図に示すように、x+1 は実際には 3*sizeof(int) バイトだけ移動されます。
なので、k+1 は実際には sizeof(int) バイトだけ移動されます。
なので、y+1 は実際には 3*3*sizeof(int) バイトだけ移動され、これは配列の最後のバイトに移動します。 要素の後の要素。図に示すように:
なので、q+1 は実際には 3*sizeof(int) バイトだけ移動します。
なので、z+1 は実際には sizeof(int) バイトだけ移動されます。
PHP中文网2017-04-21 11:19:34
一階の回答者さんがとても良く書いてますので、拡大してください
ポインタの値は配列のアドレスです
int (* pa)[5];
pa++;pa は 20 バイト戻ります (5*4)
対照的に、配列内の要素はポインター (int*) です
int *pa[5];
pa++;pa は 4 バイト戻ります
高洛峰2017-04-21 11:19:34
古い投稿を再投稿して申し訳ありません。私がこれを偶然見たのは、過去に組み込みプログラミングを行っていたとき、ポインタ変数にメモリ アドレスを直接割り当てるなど、配列とポインタが頻繁に使用されていたためです (これは通常のアプリケーションでは通常使用されません)。&arr を見つけたことがなかったからです。前にarrとの違いは何ですか?今日具体的に確認したところ、これはコンパイラに依存することがわかりました。一部のコンパイラは、配列とポインタを別々に扱います。配列名のアドレスを取得することは、配列を特定の形式のポインタとみなします。この場合、ポインタは 1 つだけジャンプします。配列要素のメモリですが、配列全体のメモリというものは存在しません。