2

コンテストの質問紙でこのプログラムを見つけました。

#include <iostream>
void main() 
{    
    int a[5] = { 1, 2, 3, 4, 5 };
    int *ptr = (int*)(&a + 1);
    printf("%d %d ",*(a + 1), *(ptr - 1));
}

出力は2 5

5 行目を and に変更するint *ptr=(int*)(&a);printf("%d %d ",*(a + 1), *(ptr));

出力は次のようになります2 1

最初のケースでptrは の最後のアドレスを取得array+1し、2 番目のケースptrでは配列の同じアドレス ( のアドレスa) を取得しました。

ptr私の疑問は、 a がインクリメントされて割り当てられたときと、インクリメントせずにa割り当てられたときに、この割り当てが異なる種類の動作を示すのはなぜptrですか?

4

3 に答える 3

5

配列のアドレスを取得すると、5 つの int の配列 (つまりint(*)[5]) へのポインターが得られます。そのポインターをインクリメントすると、5 int の配列のサイズだけ移動します。したがって、配列のシーケンス内の次の配列を指します (実際に配列のシーケンスがある場合)。次に、そのポインターを に変換すると、2 番目の (存在しない) 配列int*の最初intのポインターになります。これは、最初の配列の最後の要素の 1 つ後の要素です。それが最初の例で起こっていることです。

2番目の例では、配列へのポインターをインクリメントしていないため、に変換すると、配列int*の最初へのポインターになりますint

于 2014-12-14T06:12:36.717 に答える
3

&aはサイズ 5 の整数配列へのポインターであり、ptrint*. したがって、&a + 1のサイズだけインクリメントしますが、 でのint[5]ポインター演算は、int*の倍数でポインターの値を変更しますsizeof(int)。したがって、は のアドレスから&a + 1のアドレスを指しています。これを an にキャストして実行すると、 のアドレスが得られます。5*sizeof(int)aint* ptrptr-1a[4]

于 2014-12-14T06:14:33.177 に答える
2
&a + 1;

ここで、simpleaは配列のベースアドレス、つまり最初の要素のアドレスを指します。あなたが言うと、a+1コンパイラはに+1適用されpointer to an intます。したがって、次の整数にジャンプするオフセットによってインクリメントされます。

ただし、 という場合は&a、その配列要素 ( 型int [5]) のアドレスを意味します。したがって、それに 1 を追加すると、次のオフセットがその型の次の配列、つまり間接的に配列の 1 つ前の末尾になることを意味します。one-past-array 要素のアドレスを取得することは、逆参照しない限り問題ありません

于 2014-12-14T06:18:23.643 に答える