char example[] = {'H', 'e', 'l', 'l', 'o', ',', ' ', 'w', 'o', 'r', 'l', 'd', 0};But since this syntax would drive everybody nuts even faster than the rest of C does, the following shorthand version does exactly the same thing: char sample_array[9][16] = { "Zero", "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight" };Because the compiler is capable of counting the elements of an initializer, it can work out that there are nine strings there without you being so explicit about it; you could use sample_array[][16] instead of sample_array[9][16] and end up with the same data structure.Z e r o \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0O n e \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0T w o \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0T h r e e \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0F o u r \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0F i v e \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0S i x \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0S e v e n \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0E i g h t \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0To output the string at array index 2, you could use
puts(sample_array[2])and what would come out on the console isTwo(puts() adds the newline). To get the value of the second character of the fourth string, you'd use
sample_array[3][1].puts() in stdio.h, you will see that it's expecting its parameter to be a const char * i.e. pointer to char, not a string. Why does it work?expression[index]is exactly equivalent to
*(expression + (index))Given that, let's look at the
sample_array[2] expression that got passed to puts() above, and work out what it actually means.sample_array[2]is the same as
*(sample_array + 2)Now,
sample_array is an array expression; we're about to do arithmetic on it (we're adding 2) so we need the automatic conversion to turn it into a value. The type of sample_array is "9-element array of 16-element array of char", so the result of automatic conversion will be of type "pointer to 16-element array of char" and what it will point to is the first element of sample_array: the region of memory containingZ e r o \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0The result of adding 2 to that pointer's value is to bump it along by the size of two of the things it points to, resulting in a pointer to the third element of sample_array: the region of memory containing
T w o \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0The result of dereferencing that (which is what the prefix * operator does) is an array expression identifying (rather than pointing to) the third element of sample_array. That expression is of type "16-element array of char", and it in turn undergoes automatic conversion before being passed to
puts(), which ends up seeing a pointer to char, just as its prototype said it should. char *sample_array[] = { "Zero", "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight" };That declaration would create an in-memory structure arranged like this:(pointer)(pointer)(pointer)(pointer)(pointer)(pointer)(pointer)(pointer)(pointer)Z e r o \0O n e \0T w o \0T h r e e \0F o u r \0F i v e \0S i x \0S e v e n \0E i g h t \0All nine of those pointers are pointers to char. The first one points to the 'Z' in "Zero"; the second one to the 'O' in "One" and so on. That group of nine pointers is sample_array - an array of pointers to char - and the text itself isn't actually named. In fact, the text will probably end up in a memory region quite distant from the pointer array. Note that the text is no longer padded with extra zeroes.
puts(sample_array[2]), and you can still get the value of the second character of the fourth string with sample_array[3][1].sample_array[2] being passed to puts() again.sample_array[2]is the same as
*(sample_array + 2)Now,
sample_array is an array expression; we're about to do arithmetic on it (we're adding 2) so we need the automatic conversion to turn it into a value. The type of sample_array is "9-element array of pointer to char", so the result of automatic conversion will be of type "pointer to pointer to char" and what it will point to is the first element of sample_array. The result of adding 2 is to bump it along by the size of two pointers-to-char, resulting in a pointer to the third element of sample_array. The result of dereferencing that pointer is the value of the third element, which is itself a pointer: to the 'T' in "Two". Because that's a pointer value, not an array value, it needs no further conversion before being passed to puts().sample_array[3][1]? Well, sample_array[3][1] means the same thing as *(sample_array[3] + 1). Since sample_array[3] contains a pointer to the 'T' in "Three", adding 1 to it will yield a pointer to the next char along (the 'h' in "Three") and the dereference will yield that 'h' itself.malloc(), and save the resulting pointers into the array. You need to take care with malloc() and free() to avoid invalid memory references and memory leaks, as well as doing all the bounds checking you'd need for the simpler method.If there are fewer initializers in a brace-enclosed list than there are elements or members of an aggregate, or fewer characters in a string literal used to initialize an array of known size than there are elements in the array, the remainder of the aggregate shall be initialized implicitly the same as objects that have static storage duration.6.7.8.10:
If an object that has automatic storage duration is not initialized explicitly, its value is indeterminate. If an object that has static storage duration is not initialized explicitly, then:This makes sense from an implementation point of view, as well. It allows the compiler to initialize automatic data structures using a simple memcpy() from an unnamed static initializer of the same type, which was itself built using the same logic used for initialized named statics.
- if it has pointer type, it is initialized to a null pointer;
- if it has arithmetic type, it is initialized to (positive or unsigned) zero;
- if it is an aggregate, every member is initialized (recursively) according to these rules;
- if it is a union, the first named member is initialized (recursively) according to these rules.
In c++, use the string class, then make an array of them.
In c (someone will be along soon to correct if I'm wrong) you need to treat a string as an array of chars, so what you're actually looking for is a 2d array of chars.
Do you know how big the arrays have to be, or does it have to be decided at runtime?
posted by handee at 5:07 AM on September 27, 2008