【问题标题】:Why are arrays not lvalues? [duplicate]为什么数组不是左值? [复制]
【发布时间】:2015-01-21 01:59:15
【问题描述】:

我了解 C 标准禁止将数组用作(可修改的)左值,即在赋值的左侧:

int lhs[4], rhs[4] = {0, 1, 2, 3};
lhs = rhs;  /* illegal! */

现在,我一直想知道为什么会这样。我可以看到上面的语句(以及写入数组的任何其他赋值)被定义为等同于

memcpy((void *) lhs, (void *) rhs, sizeof(lhs));

并施加确保rhs 对用户足够大的负担,但没有决定应该是这种情况。

然而,一个非常相似的例子确实工作得很好:

struct { int a[4]; } lhs, rhs = {{0, 1, 2, 3, 4}};
lhs = rhs;

只需将数组包装在一个结构中,我们就可以准确地得到上述行为,即赋值lhs = rhs等价于:

memcpy((void *) &lhs, (void *) &rhs, sizeof(lhs));

这种(我觉得)不一致的原因是什么?允许将数组赋值解释为memcpys 有什么问题吗?

【问题讨论】:

  • 这里回答:stackoverflow.com/a/17691191/14955(向下滚动到 Edit2:真正的原因)
  • 一个数组名一个左值。我认为您要问的是为什么数组不可分配。
  • @Thilo - “真正的原因”也不能很好地解释这一点。对于大多数处理器,访问数组不需要运行时指针。在编译时,数组的大小(对于 C 的早期版本)和相对(相对于目标文件)位置都是已知的,因此数组可以是可分配的。您可以使用数组定义一个结构作为它的唯一成员,并且该结构是可分配的。早于 C 的其他语言(例如 APL 或 Cobol)允许分配数组,所以我不清楚为什么选择它以 C/C++ 中的方式实现数组。
  • 我觉得“真正的原因”并没有回答我的问题。当然,您不能“覆盖”内存 location(数组可以被解释为它;这似乎与 Ritchie 的直觉有些一致),但您可以写入它的 contents (就像结构一样)。除此之外,很明显,分配给指针 value 是没有意义的(不是双关语),但是 数组不是指针,它们的行为就像它们在某些上下文中一样.为什么你不能将赋值的左侧定义为 not 是这些上下文之一?

标签: c arrays lvalue


【解决方案1】:

C 应该是一种低级语言,不会将潜在的内存或耗时的任务隐藏在简单的语法后面。一个操作员生成一个汇编指令;对于更复杂的东西调用一个函数。在早期的 C 中,你也不能分配结构,也不能在函数之间传递它们(你会传递一个指针)。

编辑:

一个结构是一个值。它的大小是静态的并且在编译时是已知的。一个数组是多个值,大多数数组都是动态分配/重新分配的。它们的大小在编译时是未知的,因此编译器不知道要分配和复制多少内存。

int *a, *b;
a = malloc(/* value based on e.g. user input */);
b = a; /* compile this into what? */

为了使其工作,C 必须在内部将数组的大小与指针或指向的数据一起存储。这个决定留给了程序员。

【讨论】:

  • 你所说的“早期C”是什么意思?我知道的每个 C standard 都允许分配结构,因此您的论点不适用于任何可以明智地称为 C 的语言。除此之外,如果后来确实将结构分配添加到该语言中,为什么不包括数组赋值?
  • 关于您的编辑:这不是我正在谈论的一个示例-您的代码甚至不包含数组,而且它可以编译很好(将 pointer a 的值分配给 pointer b)!
猜你喜欢
  • 2011-09-17
  • 2020-01-03
  • 2020-07-11
  • 2015-02-06
  • 1970-01-01
  • 1970-01-01
  • 2016-04-24
  • 2015-02-26
  • 1970-01-01
相关资源
最近更新 更多