我想知道为什么第一个语句有效,为什么不能在 c++ 中使用第二个语句
char a[10]="iqbal"; // it works
a="iqbal"; // does not work
我想知道为什么第一个语句有效,为什么不能在 c++ 中使用第二个语句
char a[10]="iqbal"; // it works
a="iqbal"; // does not work
严格来说,数组不是指针!并且数组(数组的基地址)不能是可修改的左值。即它不能出现在赋值运算符的左侧。数组仅在某些情况下衰减为指针。阅读这篇SO 帖子以了解数组何时衰减为指针。这是另一篇很好的文章,它解释了数组和指针之间的区别
还可以在此处阅读有关左值和右值的信息,以便您了解不能出现在 LHS 上的事物=
char a[10]="iqbal"; // 有用
在这种情况下,内部发生的是
a[0] = 'i';
a[1] = 'q';
.
.
a[5] = '\0';
所以一切都很好,array[i]
可修改的左值也是如此。
a="iqbal"; // 不起作用
在内部,这大致相当于
0x60000(Address of a, but is a simple number here ) = Address of "iqbal"
这是错误的,因为我们不能为数字分配一些东西。
char 数组 a 将是静态的,如果您像这样初始化它,则无法更改。无论如何,您永远不能在 c 中分配字符串 a="iqbal"。为此,您必须使用 strncpy 或 memcpy。否则,您将尝试覆盖指向字符串的指针,这不是您想要的。
所以正确的代码会做这样的事情:
char a[10];
strncpy(a, "iqbal", sizeof(a) - 1);
a[sizeof(a) - 1] = 0;
-1 是为终止零保留一个字节。请注意,您必须自己检查字符串是否为空终止。糟糕的api。有一个 strlcpy() 调用可以为您执行此操作,但它不包含在 glibc 中。
为什么第一个语句有效,为什么在 C++ 中没有第二个
因为它们是不同的陈述,几乎完全不相关。不要因为他们都使用这个=
符号而感到困惑。在一种情况下,它代表对象初始化。在另一种情况下,赋值运算符。
您的第一行是合法的,因为初始化聚合是合法的,包括字符数组。
您的第二行不合法,因为分配给数组是不合法的。
由于这是 C++,我可以建议您避免使用裸数组吗?对于字符串使用std::string
. 对于其他数组,请使用std::vector
. 如果这样做,您的示例将变为:
std::string a = "iqbal"; // it works
a="iqbal"; // so does this
第一行不是语句,而是带有初始化的声明。第二行是带有赋值运算符的表达式语句。
您不能在 C 中分配数组。
但是您可以使用字符串文字的元素初始化数组。
尝试:
char a[10]="iqbal";
char *my_a = a;
并与 my_a 一起工作。
在编写 char a[10]="iqbal" 时,您正在使用字符初始化字符数组a的元素。我们可以对int类型做同样的事情(注意char类型的处理方式略有不同): int a[10]={1,2,...};
但是在声明部分之后编写以下内容将是无效的,因为a将被视为指针。所以写类似 a={1,2,...}; 或 a="iqbal" 没有任何意义!
在后者的声明之后,您不能将字符串文字分配给 char 数组。
一个不错、简单且有效的替代方法是使用std::strcpy
这样做,如下所示:
struct S
{
char name[30];
};
S s;
std::strcpy( s.name,
"The moribunds salute you." );
在 C++11 中,您可以使用 lambda 进行初始化,如下所示:
bool test = true;
/*const*/ char a[10] = { //Aggregate initialization
[=] //capture by value
()//no parameters
{ //start lambda
switch (test) {
case true: return *"test=true"; //*"xxx" don't return a pointer, but the 'string' itself
case false: return *"test=false";
} //switch
}()}; //}, close the lambda, (), call it, }; close aggregate initialization
当您的环境不支持时,这会派上用场std::string
,例如 NVidia 的 CUDA 或一些奇怪的嵌入式环境。lambda 被内联,因此在内部它转换为char a[10] = test?"xxx":"yyy";
如果您可以选择这样做,您显然希望始终使用std::string
,因为固定大小的字符缓冲区从根本上来说是个坏主意。
如果您使用std::string
,您可以使用以下方法将其转换为 char 数组:chararray = mystring.c_str();
。如果您坚持使用printf
: ,这很有用printf("s = %s", mystring.c_str());
。