【问题标题】:Why is this C-string assignment illegal? [duplicate]为什么这个 C 字符串赋值是非法的? [复制]
【发布时间】:2018-01-23 18:11:36
【问题描述】:

案例 1:char s[][6]={"Hello","world"}; 在这种情况下,一个静态数组被分配在只读内存中,然后从那里将元素复制到数组中。 在案例 2 中。

案例 2:char* s= "hello world"; 将把它放在只读内存中。

所以我的问题是为什么

char s[][6]={"Hello","world"};
s[1]="lucky"; //is illegal

因为如果元素是从只读内存复制的,那么为什么这个语句s[1]="lucky"; 不能从只读内存复制到数组,因为还为这个字符串文字分配了一个数组,然后从那里复制元素到 s[1]。 我已经阅读了很多答案,所有人都在说有什么区别,但没有人说为什么?请解释一下,因为我是初学者。

【问题讨论】:

  • 爱豆请推荐一个
  • 在 C 中你不能复制这样的字符串 - 使用 strcpy
  • char s[][6] 是一个char 类型的二维数组。您正试图将其视为char * 的数组。
  • s[1]="lucky"; 将因编译器错误而失败。它试图在s[1] 中放置一个指针,这不是一个指针变量。
  • 赋值 != 初始化

标签: c arrays


【解决方案1】:
s[1]="lucky"; //is illegal

因为数组名称不是可修改的左值。因此,它们不能出现在作业的左侧。

初始化不是赋值。正是在初始化期间,字符串文字不会衰减为指针,而是将文字的值复制到内存中,这允许我们修改它的内容。 (你展示的第一个就是一个例子)。

来自标准:6.7.9.p14

字符类型的数组可以由字符串文字或 UTF-8 字符串文字初始化,可选用大括号括起来。字符串文字的连续字节(如果有空间或数组大小未知,则包括终止的空字符)初始化数组的元素。

如果您需要复制字符串,则必须使用strcpymemcpy 等。

【讨论】:

  • @AshishDogra C 语法可能会产生误导。 char message[] = "Hallo World!" 用于初始化变量作为其定义的一部分。但是char message[20]; message = "Hallo World!" 是非法的。
  • 与其说初始化是特例,我更愿意说初始化不是赋值,这确实符合标准的说法。
  • @Nitin.: 二维数组是数组的数组...现在想想我说的话是否有误...s[0] 是一个数组。
  • 是的,@coderredoc。更正确的说法是赋值表达式的左侧是数组类型的表达式不会衰减为指针的少数上下文,而且数组类型的表达式不是可修改的左值。 (C2011 6.3.2.1/1-2) 因此,出现在赋值表达式的 LHS 上的 s[1] 不是可修改的左值。这与表达式是否是裸标识符无关。
  • @coderredoc,很抱歉回复缓慢。我不反对您将这些 cmets 中的文本合并到您的答案中。
【解决方案2】:

简单的答案是“C”并没有为程序员提供那么多奢侈。 C 中的赋值运算符仅将特定类型从右侧复制到左侧,例如intcharstruct 等,因此您可以将= 运算符用于char,但不能用于char*char[][6] 等。

其他编程语言,例如C++ 可以提​​供这种奢侈,因为您可以重载=-运算符。有一些编程语言默认支持此类操作,例如JavaScript。我希望它能澄清你的疑问。

【讨论】:

  • 不,这是错误的。 C 允许结构类型、联合类型和枚举类型的对象出现在赋值运算符的左侧。这些都不是内置类型。它实际上非常具体:C 明确且明确地禁止数组类型的对象出现在赋值的左侧。
  • @JohnBllinger:感谢您的评论,我修改了答案。
  • 不,你仍然没有抓住重点。并不是只允许将特定类型与赋值运算符一起使用。数组类型的对象——只有那些,在 C 支持的所有类型族中——在任何情况下都不能出现在赋值的 LHS 上。此外,用“奢侈”或没有“奢侈”来描述它是不受欢迎的,尤其是在与其他语言形成对比时。请不要参与语言战争。
  • @JohnBillinger:我欢迎你的 cmets :-)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-17
  • 1970-01-01
  • 2020-09-08
  • 2021-08-21
  • 1970-01-01
  • 2019-06-18
相关资源
最近更新 更多