写真が役に立ちます — ASCII Art は楽しいです (しかし面倒です)。
char *stuff[] = {"hello","pie","deadbeef"};
+----------+ +---------+
| stuff[0] |--------->| hello\0 |
+----------+ +---------+ +-------+
| stuff[1] |-------------------------->| pie\0 |
+----------+ +------------+ +-------+
| stuff[2] |--------->| deadbeef\0 |
+----------+ +------------+
ポインターの 1D 配列に割り当てられたメモリは連続していますが、配列に保持されているポインターがメモリの連続したセクションを指しているという保証はありません (これが、ポインター行の長さが異なる理由です)。
char stuff[3][9];
strcpy(stuff[0], "hello");
strcpy(stuff[1], "pie");
strcpy(stuff[2], "deadbeef");
+---+---+---+---+---+---+---+---+---+
| h | e | l | l | o | \0| x | x | x |
+---+---+---+---+---+---+---+---+---+
| p | i | e | \0| x | x | x | x | x |
+---+---+---+---+---+---+---+---+---+
| d | e | a | d | b | e | e | f | \0|
+---+---+---+---+---+---+---+---+---+
2D 配列に割り当てられるメモリは連続しています。x は、初期化されていないバイトを示します。stuff[0]
は 'hello' の 'h' へのポインタであり、はstuff[1]
'pie' の 'p' へのstuff[2]
ポインタであり、'deadbeef' の最初の 'd' へのポインタです (またstuff[3]
、逆参照不可能なポインタです) 'deadbeef' の後の null バイトを超えるバイトまで)。
写真はかなり、かなり異なります。
次のいずれかを記述できることに注意してください。
char stuff[3][9] = { "hello", "pie", "deadbeef" };
char stuff[][9] = { "hello", "pie", "deadbeef" };
また、2D 配列図に示されているのと同じメモリ レイアウトになります (ただし、x はゼロになります)。