我试图将一个字符串重新分配给预先初始化的数组a [],而我所能得到的只是一个错误
main()
{
char a[] = "Sunstroke";
char *b = "Coldwave";
a = "Coldwave";
b = "Sunstroke";
printf("\n %s %s",a,b);
}
[错误]:从类型'char *'分配类型'char [10]'时出现不兼容的类型..我搜索了这个但无法找到任何原因..我还试图通过重新声明重新分配它喜欢
char a[] = "Sunstroke";
但它没有用......
但是在指针的情况下,可以像在上面的程序中那样..
答案 0 :(得分:4)
要了解这里发生了什么,两个语言规则很重要:
了解"Sunstroke"
之类的字符串文字也很重要。它是一个常量字符的静态数组,大到足以容纳字符串的所有字符,并在末尾添加终止符。所以在这种情况下,它是一个const char[10]
数组,包含九个字符,后跟零值终结符。作为 static ,数组在程序的生命周期内存储在内存中。
char a[] = "Sunstroke";
这会创建一个本地数组,并通过复制字符串文字中的字符来初始化它。
char *b = "Coldwave";
这会创建一个指针,并将其初始化为指向文字本身。请注意,这很危险:文字是const
,但指针不是,因此您可以编写尝试修改文字的代码,从而提供未定义的行为。不推荐使用此转换(当然在C ++中,我不确定C),因此编译器应该给出警告。你已经启用了所有编译器警告,不是吗?
a = "Coldwave";
这会尝试重新分配数组,但由于数组不可分配而失败。他们不是没有特别好的理由;这就是语言演变的方式。
b = "Sunstroke";
这会将指针重新指定为指向不同的文字。这很好(除了上面提到的const
缺乏)。
如果你需要操纵字符串,那么:
<string.h>
中的库函数(或您自己的手工代码)来操作这些数组中的字符; std::string
类为您处理内存管理,分配等。答案 1 :(得分:3)
硬编码的字符串文字(例如“Coldwave”)实际上是char[]
(字符数组)类型 - 但它是未定义的行为来修改它们(C99:6.4 .5.6)。但是请注意,下面b
仍然是char*
(字符指针):
char *b = "Coldwave";
已为其分配了char[]
。没关系。但不同于此:
char a[] = "Coldwave";
char[]
的初始化。在声明变量时,您只能初始化一次变量,并且初始化是唯一可以通过这样的赋值填充数组或其他复合类型(例如结构)的情况。但是,你无法做到这一点:
char c[] = a;
因为当在赋值的右侧使用时,数组变量用作指向它们所代表的数组的指针,这就是char *b = a
有效的原因。
所以你不能用上面的变量做到这一点:
a = b;
// or
a = "Sunstroke";
是因为那会将char*
分配给char[]
- 没有好处;你只能这样做。
答案 2 :(得分:3)
对于 C ,如果我们查看c99 draft standard部分6.5.16
分配运算符段 2 说:
赋值运算符应具有可修改的左值作为其左操作数。
和部分6.3.2.1
Lvalues,数组和函数指示符段 1 表示:
[...]可修改的左值是一个没有数组类型的左值[...]
因此,由于数组不是可修改的左值,因此无法分配给它们。至于初始化部分6.7.8
初始化段 14 说:
字符类型数组可以用字符串文字[...]
初始化
在C++ draft standard中,相关部分为4.2
数组到指针转换段 1 ,其中包含:
“N T数组”或“未知T的数组”类型的左值或右值可以转换为“指向T的指针”类型的prvalue。结果是指向数组的第一个元素的指针。
prvalue是一个纯正的左值和部分5.17
分配和复合赋值运算符段落 1 ,其中包含:
[...]所有都需要一个可修改的左值作为左操作数[...]
答案 3 :(得分:1)
让我简化程序:
char a[] = "Sunstroke";
char *b = a;
假设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
只要数组的生命周期a
始终是相同的位置,就无法修改它。
b
是一个包含数组地址的指针,可以修改b
的值以指向其他位置。< / p>