0

If this code is correct:

char v1[ ]  =  "AB";     
char v2[ ]  = {"AB"};
char v3[ ]  = {'A', 'B'};
char v4[2]  =  "AB";     
char v5[2]  = {"AB"};
char v6[2]  = {'A', 'B'};
char *str1  =  "AB";
char *str2  = {"AB"};

Then why this other one is not?

char *str3  = {'A', 'B'};

To the best of my knowledge (please correct me if I'm wrong at any point) "AB" is a string literal and 'A' and 'B' are characters (integers,scalars). In char *str1 = "AB"; the string literal "AB" is defined and the char pointer is set to point to that string literal (to the first element). With char *str3 = {'A', 'B'}; two characters are defined and stored in subsequent memory positions, and the char pointer "should" be set to point to the first one. Why is that not correct?

In a similar way, a regular char array like v3[] or v6[2] can indeed be initialized with {'A', 'B'}. The two characters are defined, the array is set to point to them and thus, being "turned into" or treated like a string literal. Why a char pointer like char *str3 does not behave in the same way?

Just for the record, gcc compiler warnings I get are "initialization makes pointer from integer without a cast" when it gets to the 'A', and "excess elements in scalar initializer" when it gets to the 'B'.

Thanks in advance.

10
  • 2
    Pointers are not arrays, arrays are not pointers. The can be used in similar contexts, but they are not the same. One way they are not the same is how they are initialized. Commented Sep 28, 2016 at 9:34
  • "AB" is a string literal as you point out, but { 'A', 'B' } is not, nor any kind of array. It is data used to initialise the variable, so a) is of the wrong type, and b) more than one initialiser was provided. Commented Sep 28, 2016 at 9:39
  • This char *str3 = (char[]) {'A', 'B'}; would work ... :-) Commented Sep 28, 2016 at 10:12
  • Thanks to all ( @alk @WeatherVane @JoachimPileborg) :) That makes sense: 1) "AB" is an unnamed string already allocated by the compiler, that then can be pointed to by an array or a char pointer (without the need of allocating new memory). 2) {'A', 'B'} are only initializers. So in the end the ones that do not behave as conceptually expected are the arrays, since they can be initialized both: 1) allocating memory and initializing them(char v3[ ] = {'A', 'B'};) 2) not allocating memory but only making them point to an already allocated unnamed string (char v1[ ] = "AB";). Commented Sep 29, 2016 at 10:13
  • these two lines: char v4[2] = "AB"; char v5[2] = {"AB"}; are not correct. Because a character string is always terminated with a NUL byte. However, these two variable declarations are only allowing for 2 bytes while the actual string length is 3, not 2 Commented Sep 29, 2016 at 20:21

2 Answers 2

3

There is one thing you need to learn about constant string literals. Except when used to initialize an array (for example in the case of v1 in your example code) constant string literals are themselves arrays. For example if you use the literal "AB" it is stored somewhere by the compiler as an array of three characters: 'A', 'B' and the terminator '\0'.

When you initialize a pointer to point to a literal string, as in the case of str1 and str2, then you are making those pointers point to the first character in those arrays. You don't actually create an array named str1 (for example) you just make it point somewhere.

The definition

char *str1 = "AB";

is equivalent to

char *str1;
str1 = "AB";

Or rather

char unnamed_array_created_by_compiler[] = "AB";
char *str1 = unnamed_array_created_by_compiler;

There are also other problematic things with the definitions you show. First of all the arrays v3, v4, v5 and v6. You tell the compiler they will be arrays of two char elements. That means you can not use them as strings in C, since strings needs the special terminator character '\0'.

In fact if you check the sizes of v1 and v2 you will see that they are indeed three bytes large, once for each of the characters plus the terminator.

Another important thing you miss is that while constant string literals are arrays of char, you miss the constant part. String literals are really read-only, even if not stored as such. That's why you should never create a pointer to char (like str1 and str2) to point to them, you should create pointers to constant char. I.e.

const char *str1 = "AB";
Sign up to request clarification or add additional context in comments.

1 Comment

Thank you very much @JoachimPileborg for the detailed answer, now I understand it much better :) I think the key point I was missing is "constant string literals are themselves arrays" and its explanation. Regarding the constant part, I didn't know that either. I will check that thoroughly since I normally use char *str with strings ("AB") and modify its char elements.
0

(" ") is for string and (' ') is for character. for an string a memory has been allocated and for character not. pointers points to a memory and you must allocate an specified memory to it but for array of characters is not necessary.

3 Comments

Then, if for an array is not necessary to allocate memory, why this code is correct? char v3[ ] = {'A', 'B'}; Here you need to allocate memory and then initialize the array of characters with each element.
When you make an array in c language, a memory is allocated automatically but for pointers, you need to allocate memory by "malloc function" like this : str3 = (char *)malloc(sizeof(char)*Num);
Thanks for the feedback @M.zanousi :) I know about pointers and dynamic memory allocation. Just wondering the consistency of the array declarations in C. A) when we declare an array in C some memory is allocated automatically, and B) for a string ("") memory is allocated but not for a character (´´). Then this code char v3[ ] = {'A', 'B'}; makes sense (array allocates and chars dont, so they are put there). However, this code does not make sense for me char v1[ ] = "AB"; because there are 2 memory allocations, 1 made for the array and the other for the string "AB". What am I missing?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.