What is the difference between "abc" and {"abc"} in C?

In C specifically (I suppose this also applies to C ++), what is the difference between

char str[4] = "abc"; char *cstr = {"abc"}; 

Problems arise when I try to pass my "abc" to a function that takes char **

 void f(char** s) { fprintf(stderr, "%s", *s); } 

Doing the following results in a compiler error. If you chose char ** (to make the compiler happy) program the seg errors.

 f(&str); 

However, the following works fine

 f(&cstr[0]); 
+4
source share
5 answers

This is an example of how pointers and arrays are not equivalent in C. In particular: a rule that masses the decay of pointers is not applied recursively

This means that an array can be used as a pointer, but a pointer to an array cannot be used as a pointer to a pointer . This is what you experience here. This is why the compiler complains about inconsistent types when you do not explicitly push & str to char **. This should be your first clue that something is wrong.

The reason it calls segfault is this: the way the array automatically breaks into a pointer turns into the address of its first element. A pointer to an array is also a pointer to the address of the first element of the array. Thus, a pointer to an array and a pointer array are one and the same. In other words, str, when passed as a pointer, has a value identical to the string str. Therefore, if you try to make & str a pointer to a pointer, this will not work, since it is just a single-level pointer.

For instance,

 void f(char** pp); void g(char* p); char[] str = "abcd"; // Lets say this is allocated at address 0x1234 g(str); // Value of p in g is 0x1234 (by automatic conversion of char[4] to char*) char* p_str = &str; // Value of p_str is 0x1234 g(p_str); // Value of p in g is again 0x1234 f(str); // Illegal, no conversion of char[] to char** (obvious) f(p_str); // Illegal, no conversion of char* to char** (obvious) f(&str); // Illegal, no conversion of char*[4] to char** (less obvious) f((char**)p_str); // Ok, now you're overriding the typecheck 

But after the last call to f((char**)p_str) value of pp in f will still be 0x1234, because you did not change the value of p_str, you only suppressed the complaint about type checking. This means that * pp will be "a", not a pointer to an address containing "a". And that is why you get segfault when f tries to execute ** pp.

+4
source

The first line of the line defines an array of four bytes. These two equivalents:

 char str[4] = "abc"; char str[4] = {'a', 'b', 'c', 0}; 

The second line declares a pointer to a memory location that contains the bytes 'a', 'b', 'c' and 0. These are two equivalents:

 char *cstr = {"abc"}; char *cstr = "abc"; 

Your problem occurs when mixing char[] and char* . If the function accepts char** , you must create char* to get the address:

 char str[4] = "abc"; char *cstr = str; f(&cstr); 
+9
source

The brackets are actually a bit of a false mark.

str is an initialized array, not a pointer: the actual pointer variable does not contain the address str in your example, so you cannot take its address, and thus the expression &str creates a compilation error.

In contrast, cstr is a pointer variable that contains the address of a string constant, and the address of this pointer variable can be executed.

+1
source

So &x gets a pointer to x. But a pointer to an array is the same as an array. This is supported by the exception of the rules for the expression lvalue, in the case of the & operator, when applied to arrays, the type of the expression is not converted as a "pointer to ...". (6.2.2.1, ANSI 9899-1990.)

This means that str and &str are the same when str is an actual array. But &p , where p really a pointer, you get a bi-directional pointer, i.e. **p .

This would be much clearer if the standard just said β€œ& before array is ignored”, and I think the C dmr publications used to really say that. Instead, ANSI expresses this as a conversion rule, far from the definition of the & operator.

0
source

You might want to try

 char str[4] = {'a', 'b', 'c', 0}; 

or

 char str[4]; sprintf(str, "abc"); 
-1
source

All Articles