Home > Blockchain >  Why doesn't the C double asterisk work for creating a 2D array?
Why doesn't the C double asterisk work for creating a 2D array?

Time:09-17

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.

Memoy double array on Stack

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!

Memory double pointer on Heap

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 Initialization
...
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
C 2011 Online Draft

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.

  • Related