<二次元配列とポインタ配列>
二次元配列とポインタ配列は互換性がありますが、では違いはどこにあるのでしょうか?
例として、複数の文字列を二次元配列として宣言する場合を考えます。
char
str[3][4]={"ABC","DEF","GHI"};
この場合、3つの文字列はメモリ上のあるアドレス(例えば0x1000)から連続した領域に格納されます。
アドレス 配列要素 中身(文字データ)
0xabcd0000 str[0][0] 'A'
0xabcd0001 str[0][1] 'B'
0xabcd0002 str[0][2] 'C'
0xabcd0003 str[0][3] '\0'
0xabcd0004 str[1][0] 'D'
0xabcd0005 str[1][1] 'E'
0xabcd0006 str[1][2] 'F'
0xabcd0007 str[1][3] '\0'
0xabcd0008 str[2][0] 'G'
0xabcd0009 str[2][1] 'H'
0xabcd000a str[2][2] 'I'
0xabcd000b str[2][3] '\0'
同じ複数の文字列を、以下のようにポインタ配列として宣言することもできます。
char
*str[3]={"ABC","DEF","GHI"};
この場合、strはポインタの配列であり、個々の要素(str[0], str[1], str[2])はポインタ、つまりアドレスを格納する変数です。
アドレス 配列要素 中身(アドレス)
0xabcd0000 str[0] 0x00001000
0xabcd0004 str[1] 0x00001008
0xabcd0008 str[2] 0x00001010
実際の文字列データはどこにあるのでしょうか?それはstrの各要素が示しているアドレスにあるのです。
アドレス 中身(文字データ)
0x00001000 'A' — str[0]が指しているアドレス
0x00001001 'B'
0x00001002 'C'
0x00001003 '\0'
...
0x00001008 'D' — str[1]が指しているアドレス
0x00001009 'E'
0x0000100a 'F'
0x0000100b '\0'
...
0x00001010 'G' — str[2]が指しているアドレス
0x00001011 'H'
0x00001012 'I'
0x00001013 '\0'
この例のように、各文字列リテラルに連続したメモリが割り当てられるとは限りません。