Simplicity
Simplicity

Reputation: 48956

Two level pointers

Say we have the following array:

char *names[]={"Abc", "Def", "Ghi", "Klm", "Nop"};

If we want to create a pointer that points to the array above, why should we use a two-level pointer as follows?

char **p1 = names;

Thanks.

Upvotes: 1

Views: 878

Answers (5)

Arkku
Arkku

Reputation: 42149

Your names is an array [], of char *, i.e., an array of pointers to char.

Meanwhile p1 is a pointer which points to a pointer to char, i.e., a pointer to char *. You can assign names to it because the array decays to a pointer to its first element, and the first element of names is a pointer to char, hence names decays to a pointer to char *. This is the same type – char ** – as p1, therefore they are compatible.

(On another note, the element type of names is incorrect; the string literals are constant, and thus it should be const char *names[], and similarly p1 should be const char** – pointer to pointer to const char.)

Upvotes: 5

Ad N
Ad N

Reputation: 8396

EDIT: Thanks to the comment, the array is actually bound here: because the compiler can deduce its size from the initializers.


From its declaration, names is: an array of pointers to char. A bound array decays to a pointer to its first element. Elements of names being pointer to char, when used in an expression names is implicitly converted to a pointer to a pointer to char.

This is why you can assign names in your second line:

char **p1 = names;

So p1 points to the first element in names, which for most practical purposes is like pointing to the array (in memory, an array being juxtaposed objects). Technically, you are pointing to the first element though.

Upvotes: -1

Vlad from Moscow
Vlad from Moscow

Reputation: 311088

If you want to create a pointer that points to array

char *names[]={"Abc", "Def", "Ghi", "Klm", "Nop"};

then you have to write

char * ( *p1 )[sizeof( names ) / sizeof( *names )] = &names;

If you want to create a pointer that points to the elements of the array then you indeed should write

char **p1 = names;

In this case pointer p1 is initialized by the address of the address of the first character of string literal "Abc".

So for example expression *p1 will contain the value of the first element of array names that in turn (the value) is the address of the first character of string literal "Abc" and has type char *.

If you will apply dereferencing the second time **p1 you will get the first character of the string literal itslef that is 'A'.

For example

printf( "%c\n", **p1 );

To make it more clear let's consider a general situation. If you have an array with elements of type T like this

T a[N];

then this array in expressions is converted to pointer to its first element that will have type T *. So if you want to declare such a pointer yourself you should write

T *p1 = a;

This record is equivalent to

T *p1 = &a[0];

In your original example type T corresponds to type char * - the type of the elements ofarray names. So after substitution char * for T you will get

char * *p1 = names;
^^^^^^
  T

Upvotes: 1

ameyCU
ameyCU

Reputation: 16607

You did not create a pointer to array of pointers .It actually is pointer to first pointer of array.

If you want to create a pointer to array of pointers write something like this -

char *names[MAX];
char* (*p1)[MAX] = &names;

Upvotes: 1

Haris
Haris

Reputation: 12272

You can see it this way, when you need to point to an integer array, you need to use a pointer to int.

int arr[];
int* a;

a = arr;

So, in this context, you need a pointer to the elements in the array names[]. What are the elements in that array. Its char*. So you would need a pointer to char*. Which translates to pointer to pointer to char. That is

char *names[]={"Abc", "Def", "Ghi", "Klm", "Nop"};

char **p1 = names;

Upvotes: 1

Related Questions