Initializing an array of strings (char **s vs. char *s[])
Author |
Message |
stkmtd
|
Posted: Thu Nov 18, 2010 11:26 am Post subject: Initializing an array of strings (char **s vs. char *s[]) |
|
|
When we initialize a single string, it's perfectly valid to say
code: | char *s = "This is a string"; |
However, when we initialize an array of strings, it seems the following doesn't work:
code: | char **s = {"These", "are", "some", "strings"}; |
we get the following error:
code: | stringarr.c:5: warning: initialization from incompatible pointer type
stringarr.c:5: warning: excess elements in scalar initializer
stringarr.c:5: warning: (near initialization for ?s?) |
Strangely, if we go:
code: | char *s[] = {"These", "are", "some", "strings"}; |
the code works. I'm wondering what the difference is. In my mind:
char **s -> array of array of char
char *s[] -> array of array of char
Simply put, why can we initialize "char *s[]", and not "char **s"? |
|
|
|
|
![](images/spacer.gif) |
Sponsor Sponsor
![Sponsor Sponsor](templates/subSilver/images/ranks/stars_rank5.gif)
|
|
![](images/spacer.gif) |
OneOffDriveByPoster
|
Posted: Fri Nov 19, 2010 12:55 am Post subject: Re: Initializing an array of strings (char **s vs. char *s[]) |
|
|
stkmtd @ Thu Nov 18, 2010 11:26 am wrote: Simply put, why can we initialize "char *s[]", and not "char **s"? char ** is a scalar type. An initializer list should be used with aggregate types. An array of char is a special case in that you can initialize it with a string literal. The reason char * works with a string is because a string literal is an array lvalue (surprise) which will implicitly convert to a char *. The equivalent for your char ** case would be something like:
c: | char **x = (char *[]){"hello", "world"}; |
|
|
|
|
|
![](images/spacer.gif) |
stkmtd
|
Posted: Fri Nov 19, 2010 12:24 pm Post subject: Re: Initializing an array of strings (char **s vs. char *s[]) |
|
|
OneOffDriveByPoster @ Fri Nov 19, 2010 12:55 am wrote: stkmtd @ Thu Nov 18, 2010 11:26 am wrote: Simply put, why can we initialize "char *s[]", and not "char **s"? char ** is a scalar type. An initializer list should be used with aggregate types. An array of char is a special case in that you can initialize it with a string literal. The reason char * works with a string is because a string literal is an array lvalue (surprise) which will implicitly convert to a char *. The equivalent for your char ** case would be something like:
c: | char **x = (char *[]){"hello", "world"}; |
So, in essence, when I say "char **s", all C knows is that I have a pointer to a pointer (which is scalar, one value). Initializing with a list of values only works for aggregate types (which I gather are definitions like arrays that allow for multiple values).
So in C's mind:
char **s -> single value
char *s[] -> because we have the sq. brackets, C is smart enough to see that we're using an array.
in the case of char **s, the meaning is ambiguous (could be a list of char pointers, or a list of strings, so it avoids doing anything "fancy" (e.g. accepting a list as initialization))
I hope I'm understanding this right. |
|
|
|
|
![](images/spacer.gif) |
OneOffDriveByPoster
|
Posted: Fri Nov 19, 2010 5:32 pm Post subject: Re: Initializing an array of strings (char **s vs. char *s[]) |
|
|
stkmtd @ Fri Nov 19, 2010 12:24 pm wrote: So, in essence, when I say "char **s", all C knows is that I have a pointer to a pointer (which is scalar, one value). Initializing with a list of values only works for aggregate types (which I gather are definitions like arrays that allow for multiple values).
So in C's mind:
char **s -> single value
char *s[] -> because we have the sq. brackets, C is smart enough to see that we're using an array.
Quite accurate.
stkmtd @ Fri Nov 19, 2010 12:24 pm wrote: in the case of char **s, the meaning is ambiguous (could be a list of char pointers, or a list of strings, so it avoids doing anything "fancy" (e.g. accepting a list as initialization))
I hope I'm understanding this right. It is more a lack of motivation to have the initializer list implicitly act as a literal in the example case you had. It may be helpful to revisit the difference between char * and char [].
c: | char *s = "hi"; // s is pointer to char; points to memory owned by string literal
|
c: | char s[] = "hi"; // s is array of 3 char; s actually holds the characters of the null-terminated string
|
|
|
|
|
|
![](images/spacer.gif) |
Xupicor
|
Posted: Tue Feb 22, 2011 8:31 pm Post subject: RE:Initializing an array of strings (char **s vs. char *s[]) |
|
|
So, in other words:
char** s; - pointer to pointer to char
char* s[N]; an array of pointers to char
You can use the "[]" syntactic sugar to ease yourself, think: the compiler will fill it in on its own at compile time, since I provided it with sufficient information already (the string literal, compound literal, initializer list). |
|
|
|
|
![](images/spacer.gif) |
|
|