Reputation: 943
char names[][2] = {"abcdefg", "hijklmn", "qrstuv"};
printf("%c\n",*(*(names+0)+0));
printf("%s\n",names);
The last line in this code prints abhiqr
. However, changing the "2" will make the program print n characters from each array string (ie, abchijqrs
).
Why does this happen?
Also, on the middle line, I don't understand why I have a theory: I need two indirection operations because names is really a pointer to other pointers (the array) and the first dereference leaves me STILL with a pointer?
What resources can I use to read about C pointers in great detail?
Upvotes: 0
Views: 85
Reputation: 121397
You have two problems, which lead to undefined behaviour.
1) With a size of 2
, the array can't hold the larger string literals which are all more than two chars length.
2) You are passing incorrect type with the second call to printf()
printf("%s\n",names);
With %s
format specifier, printf()
expects a pointer to char (char *
). Whereas you pass a pointer to an array of 2 chars (char (*)[2]
).
Since modifying string literals is also undefined behaviour, you should declare the array with const
so as to not modify the string literals.
While the number of different string literals may vary, you can leave that to the compiler if you declare of array of pointers (each pointing to a string literal), which also helps not worry about the size of individual string literals.
Using array of pointers avoids copying the string literals into the array too. So you can declare the array of pointers like this:
const char *names[] = {"abcdefg", "hijklmn", "qrstuv"};
IMO, you should read a text book to get a complete understanding of pointers rather than learning specific examples without basics.
Upvotes: 2
Reputation: 25
About middle line, it goes like this:
char *john = "john";
char *anna = "anna";
Memory:
(address 0:)|j|o|h|n|\0|
(address 5:)|a|n|n|a|\0|
a == 0; // The address
b == 5;
*a == 'j'; // The data in memory at address 0
*(a+1) == 'o'; // The data in memory at address 1
char names[][5] = {"john", "anna"};
Memory:
(address 0:)|1|3|8|
(address 3:)|j|o|h|n|\0|
(address 8:)|a|n|n|a|\0|
names == 1; // Address of pointer to the start of John's name
*names == 3; // Address of first letter to John's name
**names == 'j' // The data at address 3, which is John's name's first letter
Hope this helps!
Upvotes: 1
Reputation: 6003
This line looks wrong:
char names[][2] = {"abcdefg", "hijklmn", "qrstuv"};
Shouldn't it be:
char names[][7+1] = {"abcdefg", "hijklmn", "qrstuv"};
As it is (char names[][2]
), it will be initialized as follows:
01?????
name[0] = "abcdefg";
^
Buffer overflow; name[1] points here...
01?????
name[1] = "hijklmn";
^
Buffer overflow; name[2] points here...
01????
name[2] = "qrstuv";
^
Buffer overflow; name[3] points here....
Upvotes: 2