Why can´t we assign a new string to an char array, but to a pointer?
To understand what's going on here, two language rules are important:
- Arrays are not assignable.
- An array can be converted to a pointer to its first element.
It's also important to understand what a string literal like "Sunstroke"
is. It's a static array of constant characters, large enough to hold all the characters of a string with a terminator at the end. So in this case, it's a const char[10]
array, containing the nine characters followed by the zero-valued terminator. Being static, the array is stored somewhere in memory for the lifetime of the program.
char a[] = "Sunstroke";
This creates a local array, and initialises it by copying the characters from the string literal.
char *b = "Coldwave";
This creates a pointer, and initialises it to point to the literal itself. Note that this is dangerous: the literal is const
, but the pointer isn't, so you can write code that attempts to modify the literal, giving undefined behaviour. This conversion is deprecated (certainly in C++, I'm not sure about C), so the compiler should give you a warning. You have enabled all the compiler warnings you can, haven't you?
a = "Coldwave";
This attempts to reassign the array, but fails because arrays aren't assignable. There's no particularly good reason why they aren't; that's just the way the languages evolved.
b = "Sunstroke";
This reassigns the pointer to point to a different literal. That's fine (apart from the lack of const
noted above).
If you need to manipulate strings, then:
- in C you'll need to carefully create arrays large enough for your needs, and use the library functions in
<string.h>
(or your own handcrafted code) to manipulate the characters in those arrays; - in C++, use the
std::string
class to handle memory management, assignment, etc. for you.
Hard-coded string literals such as "Coldwave" are actually char[]
(char array) types -- but it is undefined behavior to modify them (C99:6.4.5.6). Note that below, however, b
is still a char*
(char pointer):
char *b = "Coldwave";
To which a char[]
has been assigned. That's okay. It is different than this though:
char a[] = "Coldwave";
Which is an initialization of a char[]
. You can only initialize a variable once, when it is declared, and initialization is the only circumstance in which you can populate an array or other compound type (such as a struct) via assignment like this. You could not do this, however:
char c[] = a;
Because when used on the right hand side of an assignment, array variables function as pointers to the array they represent, which is why char *b = a
works.
So the reason you can't do this with the variables from above:
a = b;
// or
a = "Sunstroke";
Is because that would be assigning a char*
to a char[]
-- no good; you can only do it the other way around.
In the case of C if we look at c99 draft standard section 6.5.16
Assignment operators paragraph 2 says:
An assignment operator shall have a modifiable lvalue as its left operand.
and section 6.3.2.1
Lvalues, arrays, and function designators paragraph 1 says:
[...]A modifiable lvalue is an lvalue that does not have array type[...]
So since arrays are not modifiable lvalues you can not assign to them. As for initialization section 6.7.8
Initialization paragraph 14 says:
An array of character type may be initialized by a character string literal[...]
In the C++ draft standard the relevant sections are 4.2
Array-to-pointer conversion paragraph 1 which says:
An lvalue or rvalue of type “array of N T” or “array of unknown bound of T” can be converted to a prvalue of type “pointer to T”. The result is a pointer to the first element of the array.
a prvalue is a pure rvalue and section 5.17
Assignment and compound assignment operators paragraph 1 which says:
[...]All require a modifiable lvalue as their left operand[...]