24

我想知道为什么第一个语句有效,为什么不能在 c++ 中使用第二个语句

char a[10]="iqbal";  // it works

a="iqbal"; // does not work 
4

8 回答 8

24

严格来说,数组不是指针!并且数组(数组的基地址)不能是可修改的左值。即它不能出现在赋值运算符的左侧。数组仅在某些情况下衰减为指针。阅读这篇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"

这是错误的,因为我们不能为数字分配一些东西。

于 2012-04-10T12:20:43.050 回答
6

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 中。

于 2012-04-10T12:27:33.110 回答
3

为什么第一个语句有效,为什么在 C++ 中没有第二个

因为它们是不同的陈述,几乎完全不相关。不要因为他们都使用这个=符号而感到困惑。在一种情况下,它代表对象初始化。在另一种情况下,赋值运算符。

您的第一行是合法的,因为初始化聚合是合法的,包括字符数组。

您的第二行不合法,因为分配给数组是不合法的。

由于这是 C++,我可以建议您避免使用裸数组吗?对于字符串使用std::string. 对于其他数组,请使用std::vector. 如果这样做,您的示例将变为:

std::string a = "iqbal";  // it works
a="iqbal"; // so does this
于 2012-04-10T13:35:03.770 回答
3

第一行不是语句,而是带有初始化的声明。第二行是带有赋值运算符的表达式语句。

您不能在 C 中分配数组。

但是您可以使用字符串文字的元素初始化数组。

于 2012-04-10T12:21:24.453 回答
0

尝试:

char a[10]="iqbal";
char *my_a = a;

并与 my_a 一起工作。

于 2013-07-03T23:02:23.400 回答
0

在编写 char a[10]="iqbal" 时,您正在使用字符初始化字符数组a的元素。我们可以对int类型做同样的事情(注意char类型的处理方式略有不同): int a[10]={1,2,...};

但是在声明部分之后编写以下内容将是无效的,因为a将被视为指针。所以写类似 a={1,2,...}; 或 a="iqbal" 没有任何意义!

于 2012-04-10T12:28:01.517 回答
0

在后者的声明之后,您不能将字符串文字分配给 char 数组。

一个不错、简单且有效的替代方法是使用std::strcpy这样做,如下所示:

struct S
{
    char name[30];
};

S s;
std::strcpy( s.name,
    "The moribunds salute you." );
于 2021-09-05T08:43:33.460 回答
0

在 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());

于 2021-01-16T12:04:17.630 回答