7

次のコード スニペットがあります。

char board[3][3] = {
                     {'1','2','3'},
                     {'4','5','6'},
                     {'7','8','9'}
                   };

printf("address of board : %p\n", &board);
printf("address of board[0] : %p\n", &board[0]);

両方printf()のステートメントはすべて同じ値を出力します。0x0013ff67

  1. 私の知る限り、ボード(つまり)配列名は最初のサブ配列(つまり)のアドレスを表しboard[0]

  2. board[0]最初の配列の最初の要素のアドレスを表します (つまり)board[0][0]

printf()すべてのステートメントで同じ住所が表示されるのはなぜですか? 両方のステートメントに異なるアドレスが必要です。

私はこのことにかなり慣れていないため、この動作を理解していません。教えてください。

4

4 に答える 4

5

2D 配列ですが、メモリ内では線形配列として表されます。したがって、board[0][0] と言うと、それはまだその線形配列の最初の要素を指しているため、同じメモリアドレスを指しています。

于 2011-12-29T15:36:59.187 に答える
1

もちろん、これは同じアドレスを出力します。
このような2Dアレイについて少し考えてみてください。

int ** ptr;


アドレス*ptrは同じ&(**ptr)です。

基本的に、それがあなたのコードがしていることだからです。

また、メモリ内では、2D配列が線形にマッピングされることを忘れないでください。

于 2011-12-29T16:25:18.740 に答える
1

Java や Python などのオブジェクト指向言語を知っていて、現在は C 言語を学んでいる場合もあるでしょう。考えたときの Java と C の違いchar board[3][3]は、C ではboard変数がメモリ内で隣接するメモリ アドレスにある 9 文字として表されることです。そのようです:

board: 1 2 3 4 5 6 7 8 9

C では、および と&board同じメモリ アドレスが生成されます。&board[0]&board[0][0]

これとは対照的に、Java では変数は次のように宣言されchar[][] board、そのメモリ表現は概念的に次のようになります。

board: ptr(A) ptr(B) ptr(C)
A:     1 2 3
B:     4 5 6
C:     7 8 9

whereptr(x)は のメモリアドレスを指しますx。したがって、Java では、 はboardとは異なるメモリ アドレスを指しますboard[0]


C では、&board は &board[0] および &board[0][0] と同じメモリ アドレスを生成します。しかし、最初の要素には、board[0][0] (または) *board[0] (または) **board 経由でのみアクセスできます。なんでそうなの??

&boardand&board[0]とは同じアドレスを生成しますが、C 言語の型システムにより、値&board[0][0]にアクセスできません。charCコンパイラでは、型は(概念的に)次のとおりです。

board:       type char[3][3]
board[0]:    type char[3]
board[0][0]: type char

type の変数を想定すると、次のcharように記述できます。

char c;
c = board[0][0];

しかし、書くことはできません:

char c;
c = board;    // Error
c = board[0]; // Error

割り当ての左側の型が右側の型と互換性がないためです。

アドレスが を指していることが確実な場合はchar、型キャストを使用できます。

char c;
c = *(char*)board;    // Works OK
c = *(char*)board[0]; // Works OK

欠点は、そのような型キャストがコーディングのバグにつながる可能性があることです。

于 2011-12-29T17:23:53.027 に答える
1

私の知る限り、ボード(すなわち)配列名は最初のサブアレイ(すなわち)ボード[0]のアドレスを表します

boardこれは、 がこれらのコンテキストの外で使用されている場合にのみ当てはまります

  • &演算子のオペランドとして
  • のオペランドとしてsizeof

いずれかが当てはまる場合、expressionboardは配列を表し、配列の型 ( char[3][3]) を持ち続けます。それに演算子を適用する&と、配列のアドレスが取得されます。これはもちろん、最初の要素のアドレスに等しく、型が (char(*)[3][3]ではなくchar(*)[3]) 異なるだけです。配列について当てはまるのと同じことが、boardその最初のサブ配列についても当てはまりますboard[0]

これらのコンテキストの外で使用すると、最初の要素 (この場合は部分配列) のアドレスが取得されます。そのアドレスはオブジェクトではなく単なる値です。値にはアドレスがありませんが、オブジェクトにはアドレスがあります。それに適用しようとする&と失敗します。例えば

// error: trying to apply '&' on something that has no address
&(1 ? board : board)

上記はすべて C に適用されることに注意してください。必ずしも C++ ではありません。

于 2011-12-29T15:36:50.370 に答える