I am confused between the following two ways:
char var[3][15] = {\"Hello_world!\", \"good\", \"bad\"}; // as known this is for an 2D array.
char *var[3] = {\"H
The first is actually creating a block of 45 (3*15) bytes in memory, with a base at some memory location that will be called var
. C will let you address these as a two-dimensional array so that var[a][b]
is the same as *(var + a*15 + b)
. The compiler will then pre-fill those 45 bytes with your strings in the right locations to maintain the 2D-array feel.
The second method is allocating one block of memory with 3 pointers. If your pointers are 8 bytes each, then var
is a 1D array of 24 (3*8) bytes. In addition, C will create some other arrays somewhere else in memory with your data strings. It will then point the former to the latter. That is, the following is roughly equivalent to your second method:
char s1[] = "Hello_world!";
char s2[] = "good";
char s3[] = "bad";
char *var[3] = { &(s1[0]), &(s2[0]), &(s3[0]) };
Note however that the equivalence from the first method of var[a][b] == *(var + a*15 + b)
is not maintained. For example, var[0]
will point to s1
, which could technically be anywhere in memory (and has no relationship to where s2
or s3
are). Then var[0][b]
is some offset from that location.
There's two types of two dimensional arrays, and you have both types there.
With the first one, it's an array of 5 char[15]
objects, which are layed out sequentially in memory. Unused bytes in the end of each "row" are (in your particular case but not always) filled with zeros. This is what most people think of when you say a "two dimensional array", but some people call it a "square" array to distinguish it from the other type. When you initialize it, the string literals are copied into the array directly.
[0][ 0] = 'H'
[0][ 1] = 'e'
...
[0][14] = '\0' (end of each row is filled with zeros)
[1][ 0] = 'G'
[1][ 1] = 'o'
...
[3][13] = '\0' (end of each row is filled with zeros)
[3][14] = '\0' (end of each row is filled with zeros)
The second one is an array of 5 char*
(pointers) which usually refers to an array of char
objects that do not have to be the same size. If they do point at arrays of char objects, this can be accessed as a two dimensional array. Since the length of each array may be a different size, this is referred to as a "jagged array". In your code, there's three "rows", the first is 13 chars long, the second is 5 chars long, and the third is 4 chars long. The first index of the array is sequential in memory, but arrays forming the "inner" index can be anywhere in memory. When you initialize it, this forms a one-dimensional array that points at the actual string literals. Together, they form a two-dimensional array.
[0] -> "Hello_world!"
[1] --------------------------------->"good"
[2] ---------------------->"bad"
The first is a 2D array of chars. The second is a 1D array of char * (pointers).
The first is a two-dimensional array.
The second is a one-dimensional array of pointers. If those pointers point to arrays then it will also be a two-dimensional array, but that isn't guaranteed simply by looking at the types.
For example, you could have an array of 5 NULL
pointers:
char *var[5] = {0, 0, 0, 0, 0};
In this case it certainly is not a two-dimensional array, and trying to access var[i][j]
will result in undefined behaviour (most likely a memory access error, or "segfault").