【问题标题】:c string basics, why unassigned?c字符串基础,为什么未赋值?
【发布时间】:2011-04-17 12:18:40
【问题描述】:

我正在尝试学习基础知识,我认为声明一个 char[] 并为其分配一个字符串会起作用。 谢谢

int size = 100;
char str[size];

str = "\x80\xbb\x00\xcd";

给出错误“分配中的类型不兼容”。怎么了? 谢谢

【问题讨论】:

标签: c string char declaration variable-assignment


【解决方案1】:

您不能使用=运算符分配数组内容。这只是 C 语言设计的一个事实。你可以在声明中初始化一个数组,比如

char str[size] = "\x80\xbb\x00\xcd";

但这是与赋值不同的操作。 请注意,在这种情况下,额外的 '\0' 将被添加到字符串的末尾。

“不兼容类型”警告来自语言如何处理数组表达式。首先,字符串字面量存储为具有静态范围的char 数组(意味着它们存在于程序的整个生命周期中)。所以字符串字面量“\x80\xbb\x00\xcd”的类型是“4 5-element array of char”。但是,在大多数情况下,数组类型的表达式会隐式地从“T 的 N 元素数组”类型转换(“衰减”)为“指向 T 的指针”,表达式的值将是第一个地址数组中的元素。所以,当你写声明时

str = "\x80\xbb\x00\xcd";

字面量的类型已从“4 5 元素数组char”隐式转换为“指向char”的指针,但赋值的目标是类型“100- char" 的元素数组,并且类型不兼容(除了数组表达式不能成为 = 运算符的目标这一事实之外)。

要将一个数组的内容复制到另一个数组,您必须使用库函数,如memcpymemmovestrcpy 等。此外,要使strcpy 正常工作,源字符串必须是0 终止。

编辑根据 R 在下面的评论,我已经删除了答案中更愚蠢的部分。

【讨论】:

  • 字符串文字 "\x80\xbb\x00\xcd" 已经包含一个终止 0,因此在将其用作初始值设定项时谈论“添加”最后一个 0 是一种误导。此外,C 中部分初始化的对象总是将对象的其余部分填零。这不是特定于字符串的。
【解决方案2】:

str 是数组的名称。数组的名称是第 0 个元素的地址。因此,str 是一个指针常量。不能改变指针常量的值,就像不能改变常量一样(例如,不能做 6 = 5)。

【讨论】:

  • 是的,str 是一个字符数组。但是名称 str 本身,当在该上下文中使用时,是一个指针常量。也许我使用的术语不同,但是在这种情况下使用 str 时,您还能称其为什么,str = "\x80\xbb\x00\xcd";
  • "数组名是第0个元素的地址,所以str是一个指针常量。"您似乎对此声明有疑问,所以我会澄清一下。我将地址称为指针常量。例如,假设你有 int x;整数 *y ; y = &x ;在这里,&x [我和我的同事称之为] 一个指针常量——它是一个值,它是内存中某个其他位置的地址,它不能更改。它不是指针。除此之外,我的帖子还有什么问题?
  • 问题在于表达式str 并不总是被视为指针。以下是相关段落(第 6.3.2.1 节,第 3 段)“除非它是 sizeof 运算符或一元 & 运算符的操作数,或者是用于初始化数组的字符串文字,否则为表达式类型为''array of type''的表达式被转换为类型为''pointer to type''的表达式,它指向数组对象的初始元素并且不是左值。如果数组对象具有寄存器存储类,则行为未定义。”强调我的。
  • 另外,您所说的指针常量通常称为右值(即表达式的值)。
【解决方案3】:

char a[100] = "\x80\xbb\x00\xcd";char a[] = "\x80\xbb\x00\xcd";

【讨论】:

    【解决方案4】:

    这实际上是学习一门编程语言最困难的部分之一...... str 是一个数组,即已保留并标记为的内存的一部分(大小乘以一个字符,因此大小为字符)海峡str[0] 是第一个字符, str[1] 第二个字符... str[size-1] 是最后一个字符。 str 本身,没有指定任何字符,是一个指向你创建时创建的内存区域的指针

    char str[size]
    

    正如 Jerry 所说的那样,在 C 中你不能那样初始化数组。你需要从一个数组复制到另一个数组,所以你可以做这样的事情

    strncpy(str, "\x80\xbb\x00\xcd", size); /* Copy up to size characters */
    str[size-1]='\0'; /* Make sure that the string is null terminated for small values of size */
    

    总结:区分指针、内存区域和数组非常重要。

    祝你好运 - 我敢肯定,您将在比您想象的更短的时间内掌握这些概念 :)

    【讨论】:

    • no str 不是指针。做一个sizeof str 看看有什么不同。看到 str 的最简单方法是“静默”转换为表达式“右侧”的指针,而不是赋值语句的左侧。
    • 是的,Jens,你是对的——我的立场是正确的。非常感谢您指出:)
    • 另外,您在“正如 Jerry so clear said”开头的段落中误用了 initialize 这个词。
    • 抱歉,英语不是我的主要语言。
    【解决方案5】:

    当用作 Rvalue 时,char-array 可以隐式转换为 char*,但用作 Lvalue 时不能 - 这就是赋值不起作用的原因。

    【讨论】:

      【解决方案6】:

      要将字符串文字分配给str 数组,您可以使用字符串复制函数strcpy

      【讨论】:

      • 更准确地说:您复制字符(字符串“内容”)而不是“分配”一个值。
      • 是的,分配不正确。我想指出如何设置 str 数组的可能性。
      【解决方案7】:

      您可以使用字符串文字来初始化 char 数组,但不能分配 char 数组(就像您可以分配任何其他数组一样) )。 OTOH,您可以分配一个指针,因此允许以下操作:

      char *str;
      
      str = "\x80\xbb\x00\xcd";
      

      【讨论】:

      • 嗯。感谢您的帮助。这对我来说很奇怪,我可以声明 str[size],然后使用 fgets(3) 之类的东西写入该内存,或者使用 strcpy(str2, str) 写入它,但不能设置 str = "string这里”;这是为什么呢?
      • 在处理字符串文字时我会使用const char*
      • @alfo:这只是 C 不允许您通过使用 = 将另一个数组的内容分配给它来修改数组。 为什么并没有什么深刻的原因 - 只是该语言要求您使用另一种机制(通常为memcpy())来做到这一点。
      猜你喜欢
      • 2012-11-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-10-13
      • 2016-04-01
      • 2011-09-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多