简体   繁体   中英

Why can´t we assign a new string to an char array, but to a pointer?

i was trying to reassign a string to a pre-initialized array a[], and all i could get was an error

main()
{
    char a[] = "Sunstroke";
    char *b = "Coldwave";

    a = "Coldwave";
    b = "Sunstroke";
    printf("\n %s %s",a,b);
}

[Error]: incompatible types when assigning to type 'char[10]' from type 'char *'.. i searched for this but was unable to find any reason.. i also tried to re-assign it by redeclaration like

char a[] = "Sunstroke";

but it didnt worked...

but in case of a pointer it was possible as in above program..

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 NT” 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[...]

Let me simplify the program to:

char a[] = "Sunstroke";
char *b = a;

Assume that the address of a is 100, then in memory, it looks like this (illustrating only the size of pointer and endian-ness etc. may vary):

[S] [u] [n] [s] [t] [r] [o] [k] [e] [\0]         ...       [0] [0] [0] [100]
100 101 102 103 104 105 106 107 108 109                           200
 ^                                                                 ^
 |                                                                 |
 a                                                                 b

As long as the life cycle of the array, a will always be the same place, you can't modify it.

b , on the other hand, is a pointer that contains the address of the array, you can modify the value of b to point to other places.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM