char string1[3][4]={"koo","kid","kav"}; //This is a 2D array
char * string[3]={"koo","kid","kav"}; //This is an array of 3 pointers pointing to 1D array as strings are stored as arrays in memory
char (*string1Ptr)[4]=string1; //This is a pointer to a 1D array of 4 characters
//I want to know differences between string1Ptr(pointer to array mentioned in question) and string(array of pointers mentioned in question). I only typed string1 here to give string1Ptr an address to strings
Besides the fact that string
can point to strings of any size and string1Ptr
can only point to strings of size 4 only(otherwise pointer arithmetic would go wrong), I don't see any differences between them.
For example,
printf("%s\n", string1[2]); // All print the same thing, ie, the word "kav"
printf("%s\n", string1Ptr[2]);
printf("%s\n", string[2]);
They all seem to perform the same pointer arithmetic.(My reason for assuming string
and string1Ptr
are almost similar besides for the difference I stated above)
So what are the differences between string and string1Ptr? Any reason to use one over the other?
PS: I'm a newbie so please go easy on me. Also, I did check C pointer to array/array of pointers disambiguation, it didn't seem to answer my question.
char string1[3][4]={"koo","kid","kav"}; //This is a 2D array char * string[3]={"koo","kid","kav"}; //This is an array of 3 pointers pointing to 1D array as strings are stored as arrays in memory char (*string1Ptr)[4]=string1; //This is a pointer to a 1D array of 4 characters
Besides the fact that
string
can point to strings of any size andstring1Ptr
can only point to strings of size 4 only(otherwise pointer arithmetic would go wrong), I don't any differences between them.
They are absolutely, fundamentally different, but C goes to some trouble to hide the distinction from you.
string
is an array. It identifies a block of contiguous memory wherein its elements are stored. Those elements happen to be of type char *
in this example, but that's a relatively minor detail. One can draw an analogy here to a house containing several rooms -- the rooms are physically part of and exist inside the physical boundaries of the house. I can decorate the rooms however I want, but they always remain the rooms of that house.
string1Ptr
is a pointer. It identifies a chunk of memory whose contents describe how to access another, different chunk of memory wherein an array of 4 char
s resides. In our real estate analogy, this is like a piece of paper on which is written "42 C Street, master bedroom". Using that information, you can find the room and redecorate it as you like, just as in the other case. But you can also replace the paper with a locator for a different room, maybe in a different house, or with random text, or you can even burn the whole envelope, without any of that affecting the room on C Street.
string1
, for its part, is an array of arrays. It identifies a block of contiguous memory where its elements are stored. Each of those elements is itself an array of 4 char
s, which, incidentally, happens to be just the type of object to which string1Ptr
can point.
For example,
printf("%s\n", string1[2]); // All print the same thing, ie, the word "kav" printf("%s\n", string1Ptr[2]); printf("%s\n", string[2]);
They all seem to perform the same pointer arithmetic.(My reason for assuming
string
andstring1Ptr
are almost similar besides for the difference I stated above)
... and that is where C hiding the distinction comes in. One of the essential things to understand about C arrays is that in nearly all expressions,* values of array type are silently and automatically converted to pointers [to the array's first element]. This is sometimes called pointer "decay". The indexing operator is thus an operator on pointers, not on arrays, and indeed it does have similar behavior in your three examples. In fact, the pointer type to which string1
decays is the same as the type of string1Ptr
, which is why the initialization you present for the latter is permitted.
But you should understand that the logical sequence of operations is not the same in those three cases. First, consider
printf("%s\n", string1Ptr[2]);
Here, string1Ptr
is a pointer, to which the indexing operator is directly applicable. The result is equivalent to *(string1Ptr + 2)
, which has type char[4]
. As a value of array type, that is converted to a pointer to the first element (resulting in a char *
).
Now consider
printf("%s\n", string1[2]);
string1
is an array, so first it is converted to a pointer to its first element, resulting in a value of type char(*)[4]
. This is the same type as string1Ptr1
, and evaluation proceeds accordingly, as described above.
But this one is a bit more different:
printf("%s\n", string[2]);
Here, string
is a pointer, so the indexing operation applies directly to it. The result is equivalent to *(string + 2)
, which has type char *
. No automatic conversions are performed.
Any reason to use one over the other?
Many, in both directions, depending on your particular needs at the time. Generally speaking, pointers are more flexible, especially in that they are required for working with dynamically allocated memory. But they suffer from the issues that
Additionally, it can be be both an advantage and a disadvantage that
Generally speaking, arrays are easier to use for many purposes:
* But only nearly all. There are a few exceptions, with the most important being the operand of a sizeof
operator.