Why does this work:
char *name = "steven";
but this doesn't:
char **names = {"steven", "randy", "ben"};
Or, why does this work:
char *names[] = {"steven", "randy", "ben"};
but, again, this doesn't:
char **names = {"steven", "randy", "ben"};
CodePudding user response:
A char **p
is not a 2D array, it is a pointer to a pointer to a character. However, you can have more pointers and more characters following, resembling a kind of model of a 2D structure of characters.
C compiler interpret { "steven" }
as a 1D array of characters, because the braces are optional (standard chapter 6.7.9 paragraph 14).
As you tried, you can declare an array of pointers to a character by char *p[]
.
But if you want to have that pointer (to pointers to characters), you need to tell your compiler. The address of an array can be assigned to the pointer.
char **p = (char *[]){ "steven", "randy", "ben", };
Additional note: Since string literals are unmutable, you better add a const
for the characters. And since the address of these unnamed string literals are constant, too, you can provide another one.
const char * const *p = (const char * const []){ "steven", "randy", "ben", };
CodePudding user response:
I also wondered, what if I could answer you in the simplest way possible.
Why are you confused?
A simple pointer to integer for example allocated with 8 cells, acts in the same way as an array has a dimension of 8 cells. The only difference, that you can't see, is that a pointer that has 8 cells allocated is on a part of the memory that is called the HEAP, while a variable of type int tab[8] is allocated on the STACK. Indeed, since the cells are linked in memory, it is easy to imagine that a pointer and an array whose first cell address is sent are the same thing.
Why it doesn't work in the other case
However, when the idea comes to associate (** and [][]) Let's take the example of an int ** ;
int **tab;
tab = malloc(sizeof(int *) * 4);
//secure malloc do not forget
for (int i = 0; i < 4; i )
{
tab[i] = malloc(sizeof(int) * 3);
//secure malloc do not forget
}
and an
int[4][3];
You have a problem. To imagine, a double array type follows itself in memory, because it is the very principle of arrays.
While a double pointer has first 4 cells of type int * allocated (which follow each other in memory) and then each pointer of these 4 cells, each points to a memory area of 3 ints which follow each other. But the whole thing does not follow each other in the memory!
A way that may interest you
One thing you can do instead is to create an int ptr(*)[3];
which can point to the first element of an array of size 3, i.e. the address of an array [4][3]
for example.
CodePudding user response:
The initializer for a scalar object may not contain more than one item.
6.7.9 InitializationC 2011 Online Draft
...
Constraints
2 No initializer shall attempt to provide a value for an object not contained within the entity being initialized.
...
11 The initializer for a scalar shall be a single expression, optionally enclosed in braces. The initial value of the object is that of the expression (after conversion); the same type constraints and conversions as for simple assignment apply, taking the type of the scalar to be the unqualified version of its declared type
char **names
declares a single, scalar object, not an array, so any initializer for it must only contain a single item. That initializer may be a single string ("steven"
), optionally enclosed in braces ({ "steven" }
). However, it may not be a list of initializers.