Pictures can help - ASCII Art is fun (but painstaking).
char *stuff[] = {"hello","pie","deadbeef"}; +----------+ +---------+ | stuff[0] |--------->| hello\0 | +----------+ +---------+ +-------+ | stuff[1] |-------------------------->| pie\0 | +----------+ +------------+ +-------+ | stuff[2] |--------->| deadbeef\0 | +----------+ +------------+
The memory allocated for the 1D array of pointers is contiguous, but there is no guarantee that the pointers held in the array point to adjacent sections of memory (therefore, the lines of pointers of different lengths).
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| +---+---+---+---+---+---+---+---+---+
The memory allocated for the 2D array is contiguous. X stands for uninitialized bytes. Note that stuff[0] is a pointer to 'h' 'hello', stuff[1] is a pointer to 'p' 'pie', and stuff[2] is a pointer to the first 'd' of deadbeef '(and stuff[3] is a non-moving pointer to byte after zero byte after "deadbeef").
The images are pretty, completely different.
Please note that you could write any of them:
char stuff[3][9] = { "hello", "pie", "deadbeef" }; char stuff[][9] = { "hello", "pie", "deadbeef" };
and you will have the same memory layout as shown in the 2D array diagram (except that x will be reset to zero).
source share