【问题标题】:Assigning a string of characters to a char array将字符串分配给 char 数组
【发布时间】:2012-04-10 12:19:04
【问题描述】:

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

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

a="iqbal"; // does not work 

【问题讨论】:

标签: c++


【解决方案1】:

严格来说,数组不是指针! 而且数组(数组的基地址)不能是可修改的左值。即它不能出现在赋值运算符的左侧。数组仅在某些情况下衰减为指针。阅读此SO post 以了解数组何时衰减为指针。这里还有一个nice article,它解释了数组和指针之间的区别

还可以阅读有关左值和右值 here 的内容,以便您了解不能出现在 = 的 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"

这是错误的,因为我们不能给数字赋值。

【讨论】:

  • 其实a是一个可修改的左值,但是不能出现在赋值运算符的左边。 lvalue 和 rvalue 中 l 和 r 的含义早就丢失了。
  • a 可以是左值,但不是可修改左值,因此不能出现在=的LHS上?如果我错了,你能给我指出一些文件吗?我要去this
  • @PavanManjunath:考虑将a 作为引用数组形式参数的函数的实际参数传递。显然a 在这种情况下是一个左值,并且可以修改。并且表达式的左值或右值不依赖于上下文,因此a 是一个可修改的左值。
  • 我看不出它在内部是如何等同的。它更像 (pointer to first element of a) = (pointer to the first element of "iqbal") 虽然 "iqubal" 是一个字符串文字,但它应该衰减到一个指针,因为它不用于初始化数组跨度>
【解决方案2】:

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

【讨论】:

    【解决方案3】:

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

    您不能在 C 中分配数组。

    但是你可以用字符串字面量的元素初始化一个数组。

    【讨论】:

      【解决方案4】:

      为什么第一个语句有效,为什么第二个语句在 c++ 中无效

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

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

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

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

      std::string a = "iqbal";  // it works
      a="iqbal"; // so does this
      

      【讨论】:

        【解决方案5】:

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

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

        【讨论】:

          【解决方案6】:

          尝试:

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

          并与 my_a 一起工作。

          【讨论】:

            【解决方案7】:

            在 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,您可以使用chararray = mystring.c_str(); 将其转换为字符数组。如果您坚持使用printf: printf("s = %s", mystring.c_str());,这很有用。

            【讨论】:

              【解决方案8】:

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

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

              struct S
              {
                  char name[30];
              };
              
              S s;
              std::strcpy( s.name,
                  "The moribunds salute you." );
              

              【讨论】:

                猜你喜欢
                • 2015-06-25
                • 1970-01-01
                • 2011-02-07
                • 1970-01-01
                • 2014-06-08
                • 2012-10-16
                • 1970-01-01
                • 2012-05-03
                • 1970-01-01
                相关资源
                最近更新 更多