5

次があるとしましょう: int A [5] [2] [3]; A[1][0][0] = 4; それは〜を意味しますか :

1.) A [1] と A [1][0] はポインタですか?

2.) A[1] がポインターの場合、ポインター A[1][0] のアドレスを格納しますか?

3.) A[1][0] がポインターの場合、A[1][0][0] のアドレスを格納しますが、これはポインターではなく、4 の値を格納する単なる変数です。

上記の点が正しい場合、次のコードで同じ整数アドレスが得られるのはなぜですか。

int main(void)
{
        int A [5] [2] [3];
    A[1][0][0]=4;

    printf("%d\n\n", A[1]);
    printf("%d\n\n", A[1][0]);
    printf("%d\n\n",&A[1][0][0]);

        system("pause");
}

ここで、A[1] は別のポインター A[1][0] を指すポインターであり、したがってポインター A[1][0] のアドレスを格納すると仮定しています。そして、 A[1][0] は VARIABLE A[1][0][0] を指すポインターであるため、 VARIABLE A[1][0][0] のアドレスを格納します。

私を助けてください!

4

6 に答える 6

4

あなたの質問に適切に答えるには、多次元配列が C でどのように格納されるかを示す行優先順を読んでください。ウィキペディアの記事は少し簡潔すぎますが、次のいずれかがより明確になる可能性があります。

http://webster.cs.ucr.edu/AoA/Windows/HTML/Arraysa2.html http://archive.gamedev.net/archive/reference/articles/article1697.html http://www.ibiblio.org/ pub/languages/fortran/append-c.html

このSOの質問もあります。


行優先のストレージがどのように機能するかを知っていると仮定して、あなたのポイントへの直接的な答えとして:

int A[5][2][3]5*2*3 int の長さのメモリの連続領域を宣言します。それぞれ 3 つの int の 2 つの配列からなる 5 つの配列です。配列は線形メモリに隣り合って格納されるため、

&A[0][0][0] == A
&A[0][0][1] == A+1
&A[0][1][0] == A+(1*3)
&A[3][1][2] == A+(3*(2*3))+(1*3)+2

A[1]技術的にはポインタではなく配列です。それはint [2][3]配列です。A[5][2][3]しかし、長さが 30 int のフラットなメモリ領域を考えるよりも、考えるのがはるかに明確ではないことがわかりました。

A[0][0][0] is the first integer in that region. 
A[0][0][1] is the second integer. 
A[0][0][2] is the third integer. 
A[0][1][0] is the fourth integer in this flat region. 
A[0][1][1] is the fifth integer. 
And so on until A[1][0][0] is the eleventh integer. 

したがって、 のアドレスA[1][0][0]は の 10 個の整数A[0][0][0]です。すなわち&A[1][0][0] - &A[0][0][0] == 10。C 言語は配列とポインターの違いについて非常に緩いため、A[1]実際には「2 つの配列からなる 5 つの配列からなる配列の最初の要素」を意味するにもかかわらず、式で使用するとアドレスであるかのように解釈されます。 3 つの整数」は、「3 つの整数の 2 つの配列の配列」です。

結論は、ポインターを格納するのでA[1]なく、ポインターです。から までのすべてのメモリ アドレスは、多次元配列に整数を格納します。&A[0][0][0]&A[5][2][3]-1

ポイント (2) と (3) で考えているのは、arrays へのポインターの配列であり、これは別のものです。

これは、図を使って説明する方がはるかに簡単です。そのため、C 配列に関する適切な教科書や記事を見つける必要があります。

一般に、C のポインターと配列について学習するときは、言語自体のことは一時的に忘れて、56kb のフラット RAM を搭載した PDP-11 コンピューターで Dennis Ritchie が C を発明しているふりをすることをお勧めします。大きな方眼紙を用意し、そのセルに連続して番号を付け、それが RAM を表し、各セルが 1 バイトであると仮定します。鉛筆と紙を使ってポインタ計算を行うことができます

C はその環境で発明されたものであり、その起源を理解することで、現代の言語がより賢明になります。

補足として、この回答を書き込もうとしたときに、スタック オーバーフローのマークアップ言語が繰り返し変更され、上記の配列の例のインデックスが台無しになりました。そのため、配列の範囲外と思われる数値が表示された場合、それはエディターによって導入された間違いです。

于 2012-05-24T23:58:23.537 に答える
1

malloc動的配列がある場合 (つまり、 /で割り当てられた場合)、あなたの仮定は当てはまりますcalloc

ただし、静的配列はメモリの連続したチャンクとして割り当てられ、最初の要素への単なるポインターです。あなたが書くとき、A[X][Y][Z]それは基本的に*(A + X*YSIZE*ZSIZE + Y*SIZE + Z)ではなく と同等*(*(*(A+X) + Y) + Z)です。これにより、データへのアクセスがいくらか高速になりますが (中間ポインターにアクセスする必要はありません)、すべてのデータを 1 つのチャンクに割り当て、通常のサイズにする必要があります。

C での静的配列と動的配列の非互換性に関する詳細情報を次に示します。

于 2012-05-24T23:40:33.880 に答える
1

変数 A は 5 * 2 * 3 int で、ブロックとして一緒に割り当てられます。(つまり、30 int)。

「int A[5][2][3];」の宣言にはポインタは含まれていません。- 確保されている唯一のスペースは、30 個の int 値を保持することです。

A と添字を使用して式を記述する場合、次元が 3 つあると言ったため、アクセスまたは変更する int 値を指定するには、3 つすべてを指定する必要があります。使用する添え字が 3 つ未満の場合は、アクセス対象を部分的にしか指定していません。規則では、そのような参照は、空間全体の関連部分のアドレスに対する要求として解釈されます。

于 2012-05-24T23:41:58.240 に答える
1

c の多次元配列はポインターを使用しません。ポインターからポインターへのアクセスも同様に見えるかもしれませんが、実際のデータは連続していない可能性があり、すべてのアドレスを格納するためのオーバーヘッドがあります。C における多次元配列へのアクセスは、シンタックス シュガーの一種です。

char a[5][7][9]
a[d][h][w]  <<==>>  ((char*)a)[((9*7*d)+(9*h)+w] 

C 配列はすべて、減衰する (または自動的に配列の最初の要素へのポインターに変わる) というプロパティを共有します。結果として、

a[1]  (char[7][9])    --decay-->   ((*char)[5][9]) pointer to char array
&a[1] ((*char)[5][9])  no decay

後者ではポインタを明示的に「減衰」させますが、最初の場合は自動的に行われるため、この 2 つは同等です。

于 2012-05-24T23:39:10.940 に答える
0

少し変かもしれませんが、私の説明です。1 から 6 までの番号が付けられた 6 人の異なる人がいて、1 から 6 まで順番に並んでいると想像してください。このチーム (6 人) が 2 つのグループに分けられ、最初の 3 人 (1 から 3) がグループ A に属し、残り (4 ~ 6 人) はグループ B に属します。

[1 2 3] [4 5 6]

では、チームの最初のメンバーは誰ですか? あなたは最初のものを言うでしょう!でも、THE TEAMのグループAの最初のメンバーは誰?同じです、一人目です!

また、チームの4番目のメンバーは誰ですか? あなたは4番目と言うでしょう!では、THE TEAM の GROUP B の最初のメンバーは誰ですか?同じです、4枚目です。


同じ話があなたにも起こります。A[1] は大きな配列(チーム) の先頭へのポインターであり、A[1][0] は、大きな配列 (A[ 1])、これは同一です! 次に、&A[1][0][0] と言います。これは、大きな配列にある最初の内部配列の最初のメンバーに、あなたの番号は何ですか?と尋ねるようなものです。その後、彼は同じことを繰り返します。

異なるのは、ポインターのとその解釈方法ですが、それらの値は同一です。これは、配列が連続した方法で要素を格納するためです。

于 2012-05-25T02:22:57.063 に答える
0

Row Major Orderを読む

ええ、それはまったく役に立ちませんでした。私は、C が 1 秒間コラム メジャーであると考えていたと思います。(全ての意味を忘れて)

于 2012-05-24T23:29:59.440 に答える