1

配列へのポインターと通常のポインターとアクセス方法に関して少し混乱しています。私はこれを試しました...

int *ptr1, i;
int (*ptr2)[3];
int myArray[3] = {1, 1, 1};
int myArray1[5] = {1, 1, 1, 1, 1};
ptr1 = myArray;
ptr2 = myArray1;// compiles fine even though myArray1 contains 5 elements 
                 // and ptr2 is pointing to array of 3 elements.

printf("%d",ptr2[3]); // prints some garbage.

なぜこのステートメントはガベージを印刷するのですか? 正しい言い方は?誰でも説明できますか?

4

3 に答える 3

4

配列へのポインターを次のように宣言することもできます。

int (*ptr)[]; // ptr is a pointer to array.

あなたがするとき

ptr2 = myArray1;

コンパイラは警告メッセージをスローします。Look boss types are not compatible. 一部のコンテキストでは、配列はポインターに崩壊します。警告メッセージは、配列がポインターに崩壊するとき、崩壊した型がポインターであるためです。この場合、あなたがするとき

ptr1 = myArray; 

myArray は に減衰しint *ます。

しかし、あなたがそうするとき、

ptr2 = myArray1;

myArray1はポインター isint *に減衰しますが、の型はptr2isint (*)[]です。

警告を避けるために、あなたは言うべきです

ptr2 = &myArray1; //&myArray1 returns address of array and type is int(*)[].

なぜこのステートメントはガベージを印刷するのですか? 正しい言い方は?誰でも説明できますか?

printf("%d",ptr2[3]);// prints some garbage. 

そうだね。でも何で?最初に正しいステートメントを見てみましょう...(インデックスは3未満でなければならないことに注意してください)

printf("myArray1[%d] = %d\n", i, (*ptr2)[2]); 

(*ptr2)[i]配列要素を出力するために使用する必要があります。これは、 に言及するだけptr2で、配列のアドレスを取得するためです (一部のアドレスではありませんint)。それを逆参照することで、配列(*ptr2)のアドレスを取得します。0th element

于 2013-10-25T06:10:15.657 に答える
1

ポインターptr2は、サイズ 3 の int 配列へのポインターです。

ptr2 = myArray1;  // you may getting warning for this 

次のようにする必要があります。

ptr2 = &myArray1; // use & operator 

printf("%d", ptr2[3]);

次のようにする必要があります。

printf("%d", (*ptr2)[2]); // index can't be 3 for three size array 
 //          ^^^^^^^  

*ptr2演算子の優先順位が逆参照演算子[]よりも高いため、括弧が必要であることに注意* してください (一方、int へのポインターを使用する場合は、上記のコードのように括弧は必要ありません)。

配列へのポインタと配列のアドレスを直接使用する場合の読み取りの矛盾配列要素にアクセスするための両方の配列について説明しました。(1) int へのポインタを使用 (2) 配列へのポインタ

ptr1 = myArray;は単に検索するだけですが、配列要素には次のようにアクセスできます(ptr1[i]iは 0 から 4 である必要はありません)。

于 2013-10-25T06:10:23.333 に答える
1
int (*ptr2)[3];

(*ptr2)これは、整数配列の先頭のメモリ内の場所を含む識別子であることを意味します。言い換えれば、それptr2はアドレスです。そのアドレスには値が含まれています。その値自体が int の配列の先頭のアドレスです。

したがって、あなたが書くとき、ptr2 = myArray1あなたは基本的に「私の住所所有者の住所はmyArray1」の始まりの住所です.

したがって、 を使用して値をptr2[3]印刷すると、実際には のメモリ アドレスの値がmyArray1インクリメント3*sizeof(ptr2)された単位で印刷されます。これがゴミのように見える理由です。これはメモリアドレスです。

印刷ステートメントにある必要があるのは、(*ptr2)[3]「のアドレスをptr2取得し、そのアドレスに格納されている値を取得する。次に、その2番目のアドレスを使用して、それをインクリメントし、インクリメントされたアドレスに格納されている値を取得する」という意味3*sizeof(int)です。

C の配列は、割り当てられたメモリの連続した領域にすぎません。その理由は次のとおりです。

int *x = malloc(3*sizeof(int));

以下と同じです:

int x[3];

[]*の両方がポインターを逆参照するため、どちらかの配列の 2 番目の要素にアクセスする場合は、次のように記述できます。

int value = x[1];

また

int value = *x+sizeof(int); // Since *x would be index 0

主な違いの 2 つは、[]表記が少し読みやすくなったことですが、長さはコンパイル時に決定する必要があります。一方、*x/malloc()表記を使用すると、配列または任意の長さを動的に作成できます。

于 2013-10-25T08:01:28.543 に答える