Reputation: 1076
Why I can't define an array
char **pp={ "123", "456", "789" };
But I can define it as a char*[] ,and send it to a function that will accept it as a char **
char *pp[]={ "123", "456", "789" };
fun(pp);
void fun(char **pointerToPointer)
{
//++(**pointerToPointer);//error
printf("%s", *pointerToPointer);
}
//output::"123"
And why I can't increment
++(**pointerToPointer);
Upvotes: 4
Views: 1377
Reputation: 141554
To answer the first question, the principles might be clearer if we use a single depth of pointer. This code is illegal for the same reason:
int *ptr = { 1, 2, 3 };
In C, a braced initializer list is not an object (especially not an array). It can only be taken as a list of items from which to read initializers when an object is being initialized.
ptr
is one object, so at most one initializer could be taken, and the expected form of that initializer is a pointer (which 1
is not).
In fact this code is explicitly illegal under C11 6.7.9/11:
The initializer for a scalar shall be a single expression, optionally enclosed in braces
However, there is a gcc bug/feature where it permits excess initializers for a scalar and ignores them. Further, some compilers may "be helpful" and "only" issue a warning, and initialize ptr
to point to address 1
, wherever that might be.
"scalar" means an object that's not a struct or an array.
Since C99 you can write:
int *ptr = (int []){1, 2, 3};
which creates an array (using the same storage duration as ptr
) and points ptr
at its first element.
This array is mutable; for a non-mutable one use int const *ptr = (int const[]){1, 2, 3};
instead.
Replacing int
by char *
, we see that you could write:
char **p = (char *[]){ "123", "456", "789" };
in which case the pointers in the array are mutable, but the things they point to (i.e. the string literals) still aren't.
Note that you should always use char const *
when dealing with string literals, because they are not mutable. The fact that string literals have type char [N]
is a historical hangover from before const
was added to C. So:
char const **pp = (char const *[]){ "123", "456", "789" };
or with non-mutable pointers to strings:
char const *const *pp = (char const *const []){ "123", "456", "789" };
Upvotes: 2
Reputation: 488
Here char *pp[]={ "123", "456", "789" };
is correct because:
char
pointer, it works fine.But in case of char **pp={ "123", "456", "789" };
As CoolGuy said ++(**pointerToPointer)
it is error because it accessing 1
of "123"
string, and trying to change the value of 1
to 2
, and as these are string literals assigning can't be done. You can only see the increment value of print:
printf("%c\n", **pointerToPointer+1);
which will give output : 2
You can solve it by the solution provided by CoolGuy in the comment-
char *pp[]={ "123", "456", "789" };
to char pp[][100]={ "123", "456", "789" };
void fun(char **pointerToPointer)
to void fun(char (*pointerToPointer)[100])
It is correct because here the value of **pointerToPointer
is getting changed.
These are the reasons to me. And for the warning:
warning: excess elements in scalar initializer [enabled by default]
you can see the link in here which is the best explanation of it to me.
Upvotes: 1