[英]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我试图将一个字符串重新分配给一个预先初始化的数组 a[],但我得到的只是一个错误
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 *' 分配到类型 'char[10]' 时类型不兼容。
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:要了解这里发生了什么,有两个语言规则很重要:
It's also important to understand what a string literal like "Sunstroke"
is.了解像
"Sunstroke"
这样的字符串文字是什么也很重要。 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.所以在这种情况下,它是一个
const char[10]
数组,包含九个字符,后跟零值终止符。 Being static , the array is stored somewhere in memory for the lifetime of the program.作为static ,数组在程序的生命周期内存储在内存中的某处。
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.请注意,这是危险的:文字是
const
,但指针不是,因此您可以编写尝试修改文字的代码,从而给出未定义的行为。 This conversion is deprecated (certainly in C++, I'm not sure about C), so the compiler should give you a warning.这种转换已被弃用(当然在 C++ 中,我不确定 C),因此编译器应该给你一个警告。 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).这很好(除了上面提到的缺少
const
之外)。
If you need to manipulate strings, then:如果您需要操作字符串,则:
<string.h>
(or your own handcrafted code) to manipulate the characters in those arrays;<string.h>
的库函数(或您自己编写的代码)来操作这些数组中的字符;std::string
class to handle memory management, assignment, etc. for you.std::string
类为您处理内存管理、分配等。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).诸如“Coldwave”之类的硬编码字符串文字实际上是
char[]
(字符数组)类型——但修改它们是未定义的行为( C99 :6.4.5.6)。 Note that below, however, b
is still a char*
(char pointer):但是请注意,下面的
b
仍然是一个char*
(字符指针):
char *b = "Coldwave";
To which a char[]
has been assigned.已为其分配了
char[]
。 That's okay.没关系。 It is different than this though:
但它与此不同:
char a[] = "Coldwave";
Which is an initialization of a char[]
.这是
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.因为当在赋值的右侧使用时,数组变量充当指向它们所代表的数组的指针,这就是
char *b = a
起作用的原因。
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;是因为那会将
char*
分配给char[]
—— 不好; 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:在C的情况下,如果我们查看c99 草案标准第
6.5.16
节赋值运算符第2段说:
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:和第
6.3.2.1
节左值、数组和函数指示符第1段说:
[...]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:至于初始化部分
6.7.8
初始化第14段说:
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:在C++ 草案标准中,相关部分是
4.2
Array-to-pointer conversion第1段,它说:
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”.
“NT 数组”或“T 的未知边界数组”类型的左值或右值可以转换为“指向 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: prvalue是纯右值,第
5.17
节赋值和复合赋值运算符第1段说:
[...]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):假设
a
的地址是100,那么在内存中,它看起来是这样的(仅说明指针大小和字节序等可能会有所不同):
[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.只要数组的生命周期,
a
永远是同一个地方,你不能修改它。
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. b
,另一方面,是一个包含数组地址的指针,你可以修改b
的值指向其他地方。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.