views:

167

answers:

4

Note: This question was influenced by this answer.

The following is valid C code:

char myString[] = "This is my string";

This will allocate a string of length 18 (including the \0 character) on the stack and assign the specified value to it.

However, the following:

char myStrings[][] = {"My 1st string", "My 2nd string", "My 3rd string"};

is not valid, giving the error "array type has incomplete element type".

So I have to specify the array like this:

char myStrings[][20] = {"My 1st string", "My 2nd string", "My 3rd string"};

Where 20 is a number which is larger than my longest string.

This compiles and works as expected.

If the compiler can dynamically sense the string length when allocating a single string on the stack, why can't it do so for an array of strings?

Edit:

Just to clarify, this is not a real life programming problem I am experiencing - this is just morbid curiosity.

+2  A: 

char myString[] = "..." is a 1-Dimensional array and it will work. char myStrings[][] = {"...", "..."} is a 2-D array with (possibly) different row length, and this will not work. char myStrings[][20] is a 2D array with fixed row length and it will work.

According C standards, compiler cannot sense the length of string in 2D arrays.

But I guess, it is possible in Java.

Alphaneo
It's possible in Java because arrays of strings are always arrays of pointers.
Zarel
+5  A: 

One thing is to "sense" the length of one string. Another thing is to calculate the maximum of lengths of many strings. There's a certain intuitive qualitative difference between the two. So, the language authors probably decided that the former is simple and useful, but the latter is too compilex and less useful.

AndreyT
+1 Good answer - was more along the lines of what I was thinking.
LeopardSkinPillBoxHat
+4  A: 

Why not do:

const char* myStrings[] = {"My 1st string", "My 2nd string", "My 3rd string"};
jeffamaphone
Sometimes you need modifiable strings
pmg
+1 @jeffamaphone very nice.@pmg, I think, the intention of the person asking this question, is just to create a constant string.
Alphaneo
As pmg noted, it would mean that the resultant strings were read-only.
LeopardSkinPillBoxHat
@Alphaneo - no the question was more curiosity than anything else, but being modifiable would be useful too.
LeopardSkinPillBoxHat
True, but I've found that this is almost always what you really want in these cases. The other case is he really wants a vector<string> at which point, if he's stuck in C, he gets to write his own.
jeffamaphone
+3  A: 

Because the compiler sees this

char myStrings[][20] = {"My 1st string", "My 2nd string", "My 3rd string"};

as

char myStrings[][20] = {(char*), (char*), (char*)};

Then, errrr ... hmmm, with "compiler magic", it can copy the characters in those (char*) to the array myStrings[0] and myStrings[1], ....


Edit

You cannot have "jagged arrays" in C. Suppose you had

char my_strings[][] = {"a", "ab", "abc", "foo foo fo foo foo", "abc", "ab", "a"};

my_strings[0] needs the same space as my_strings[3] because the language mandates array elements to be contiguous, and it needs a specific size of each array.

my_strings in memory
    'a' '\0' '\0' ...  '\0' but must be a definite size
    'a' 'b'  '\0' ...  '\0' definite size
    ...
    'f' 'o'  'o'  ...  '\0'
    ...

To find the maximum size and initialize the array(s), the compiler would need to do two passes over the string literals.

pmg
The "excess" character memory for each string will not contain garbage. It will be filled with zeroes. The general philosophy used by C language when it comes to initialization is that something is either completely uninitialized (the whole thing is garbage) or completely initialized (the parts that don't have s user-supplied initializer are zero-initialized). For example, when you declare `char s[100] = "a"` not only `s[0]` and `s[1]` are initialized, but also all elements from `s[2]` to `s[99]` are guaranteed to be zero-initialized.
AndreyT
Thank you Andrey. Edited my answer
pmg