【问题标题】:Assigning strings to arrays of characters将字符串分配给字符数组
【发布时间】:2010-10-09 10:44:11
【问题描述】:

我对以下内容感到有些惊讶。

示例 1:

char s[100] = "abcd"; // declare and initialize - WORKS

示例 2:

char s[100]; // declare
s = "hello"; // initalize - DOESN'T WORK ('lvalue required' error)

我想知道为什么第二种方法不起作用。它应该看起来很自然(它适用于其他数据类型)?有人可以解释一下这背后的逻辑吗?

【问题讨论】:

    标签: c


    【解决方案1】:
    1    char s[100];
    2    s = "hello";
    

    在您提供的示例中,s 实际上是在第 1 行而不是第 2 行初始化的。即使此时您没有明确地为它赋值,编译器也这样做了。

    在第 2 行,您正在执行赋值操作,并且不能像这样将一个字符数组分配给另一个字符数组。您必须使用 strcpy() 或某种循环来分配数组的每个元素。

    【讨论】:

    • 你好为什么需要 100 个字节? char s[6]还不够吗?
    • @mLstudent33,这是OP给出的例子。
    【解决方案2】:

    当初始化一个数组时,C 允许你用值填充它。所以

    char s[100] = "abcd";
    

    基本一样

    int s[3] = { 1, 2, 3 };
    

    但它不允许您进行分配,因为s 是一个数组而不是一个空闲指针。

    的含义
    s = "abcd" 
    

    是将abcd 的指针值分配给s,但你不能更改s,因为那时没有任何东西指向数组。
    如果 schar* - 可以指向任何东西的指针,这可以而且确实有效。

    如果您想简单地复制字符串,请使用strcpy

    【讨论】:

    • 很好的答案,除了你不应该再使用普通的 strcpy 了。使用 strncpy 或 strlcpy。
    • 另外,s 应该是 const char*,而不是 char*。
    • s[0] = 'x'; s[1] = 'y'; s[2] = 'z'; s[3] = 'm'; 可以在初始化之后一个一个地替换字符串字符。
    • @RBT,也许它在您的平台上与您的编译标志一起使用,但通常这些字符串是在只读内存中定义的。写入它会导致段错误或访问冲突错误
    • 为什么?执行 char s[100]; s = "abcd"; 给出错误非常有意义,因为 s 被有效地视为 const 指针。因此,如果我们尝试在第二行中分配“abcd”,我们将尝试更改不允许的指针的值。但是如果一个 const 指针指向一个内存位置,那么内存位置的内容当然应该是可修改的。假设s 指向内存位置 1000,然后 s 包含 1000,内存位置 #1000 包含 a。我无法更改 s 来存储新的内存位置,例如2000 但我可以存储一个新角色,例如z 在内存位置 1000。
    【解决方案3】:

    C 中没有“字符串”这样的东西。在 C 中,字符串是 char 的一维数组,以空字符 \0 结尾。由于不能在 C 中分配数组,因此也不能分配字符串。文字“你好”是const char x[] = {'h','e','l','l','o','\0'};的语法糖

    正确的方法是:

    char s[100];
    strncpy(s, "hello", 100);
    

    或者更好:

    #define STRMAX 100
    char    s[STRMAX];
    size_t  len;
    len = strncpy(s, "hello", STRMAX);
    

    【讨论】:

    【解决方案4】:

    我知道这个问题已经得到解答,但我想分享一个我给在 C/C++ Facebook 群组上提出非常类似问题的人的答案。


    数组没有赋值运算符函数*。这意味着您不能简单地将 char 数组分配给字符串文字。为什么?因为数组本身没有任何赋值运算符。 (*它是一个不能改变的常量指针。)

    数组只是一个连续分配的内存区域和名称 数组的实际是指向数组第一个元素的指针。 (引自https://www.quora.com/Can-we-copy-an-array-using-an-assignment-operator

    要将字符串文字(例如 "Hello world""abcd")复制到 char 数组,您必须手动将字符串文字的所有 char 元素复制到数组中。

    char s[100]; 这将初始化一个长度为 100 的空数组。

    现在要将您的字符串文字复制到此数组中,请使用 strcpy

    strcpy(s, "abcd"); 这将从字符串文字"abcd" 中复制内容并将其复制到s[100] 数组中。

    这是一个很好的例子:

    int i = 0; //start at 0
    do {
        s[i] = ("Hello World")[i]; //assign s[i] to the string literal index i
    } while(s[i++]); //continue the loop until the last char is null
    

    您显然应该使用 strcpy 而不是这个自定义字符串文字复制器,但这是一个很好的示例,可以解释 strcpy 的基本工作原理。

    希望这会有所帮助!

    【讨论】:

      【解决方案5】:

      我会使用的是

      char *s = "abcd";
      

      【讨论】:

      • 我们大多数人都不会这样做,因为它有未定义行为的风险。以上仅对const char*安全。
      【解决方案6】:

      你可以用这个:

      yylval.sval=strdup("VHDL + Volcal trance...");
      

      在哪里 yylval 是 char*。 strdup from 完成这项工作。

      【讨论】:

      • strdup from 完成这项工作:)
      • strdup 创建一个副本并返回指向副本的指针。在这种情况下,对于 char 数组,你回到了你开始的地方,没有完成任何工作
      【解决方案7】:

      请注意,您仍然可以这样做:

      s[0] = 'h';
      s[1] = 'e';
      s[2] = 'l';
      s[3] = 'l';
      s[4] = 'o';
      s[5] = '\0';
      

      【讨论】:

      • 使用 strncpy() 更好也更容易,尽管我很确定 strncpy() 在内部确实做到了这一点。
      • 当然。但这与 's = "hello";' 非常接近事实上,这应该在 C 中实现,看看如何分配结构。
      • 我的意思是,通过在结构中分配而不是在数组中分配的成员复制没有意义。
      【解决方案8】:

      扩展Sparr's answer

      初始化和赋值是两个不同的操作,在这里碰巧使用了相同的运算符(“=”)。

      这样想:

      假设有 2 个函数,分别称为 InitializeObjectAssignObject。当编译器看到thing = value 时,它会查看上下文并调用一个InitializeObject,如果你正在创建一个新的thing。如果你不是,它会调用AssignObject

      通常这很好,因为 InitializeObjectAssignObject 通常表现相同。除了在处理 char 数组(和其他一些边缘情况)时,它们的行为不同。为什么要这样做?好吧,这完全是另一篇文章,涉及堆栈与堆等等。

      PS:顺便说一句,如果你曾经涉足 C++,以这种方式思考它也将帮助你理解复制构造函数和其他类似的东西

      【讨论】:

        【解决方案9】:

        初始化和赋值是两个不同的操作,在这里碰巧使用了相同的运算符(“=”)。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2021-12-07
          • 1970-01-01
          • 2019-10-13
          • 1970-01-01
          • 2021-07-23
          • 2015-06-25
          • 1970-01-01
          相关资源
          最近更新 更多