【问题标题】:Every expression with "array of type" will always be converted to "pointer to array of type" in C每个具有“类型数组”的表达式将始终转换为 C 中的“指向类型数组的指针”
【发布时间】:2021-04-20 18:27:58
【问题描述】:

示例代码:

int a[10]={0};
a = (void *) 0; // error: assignment to expression with array type

根据6.5.1 Primary expressions

primary-expression:
 identifier
 constant
 string-literal
 ( expression )

6.3.2.1 Lvalues, arrays, and function designators

左值是具有对象类型或除 void 之外的不完整类型的表达式; 如果左值在评估时未指定对象,则行为未定义。 当一个对象被称为具有特定类型时,该类型由用于 指定对象。 可修改的左值是没有数组类型的左值,有 没有不完整的类型,没有 const 限定的类型,并且如果它是一个结构 或联合,没有任何成员(包括,递归地,任何成员或元素 所有包含的聚合或联合)具有 const 限定类型。

我们知道a(void *) 0 都是左值表达式,a 有一个类型数组。

如果我们看下面的定义:

除非它是 sizeof 运算符或一元 & 运算符的操作数,或者是 用于初始化数组的字符串字面量,类型为“array of type”的表达式是 转换为类型为“pointer to type”的表达式,该表达式指向 数组对象并且不是左值。如果数组对象有寄存器存储类,则 行为未定义。

看起来a 的类型从array of int 转移到pointer to array of int,它变成了“可修改的左值”。但是我的 gcc 9.3.0 说:

error: assignment to expression with array type"

我很困惑。

【问题讨论】:

  • "看起来 a 的类型从 array of int 转移到 pointer to array of int" - 不,它衰减变成了 pointer to int . pointer to array of int 是完全不同的东西。 “它变成了“可修改的左值””——不,在这种情况下它不会。 数组衰减 仅在某些情况下发生(例如将数组传递给函数参数,或将其分配给变量),但这不是其中之一。因此,一旦数组初始化,就不能将 anything 分配给数组本身,只能分配给它的元素。
  • (void *) 0 在我看来不像左值
  • @RemyLebeau 感谢您的指正。函数声明中数组衰减的说明见6.7.5.3 Function declarators

标签: c types expression c99


【解决方案1】:

您错过的部分是第 6.5.16p2 节关于赋值运算符的约束:

赋值运算符应该有一个可修改的左值作为它的左操作数

数组不是可修改的左值,因此将它放在赋值的左侧是违反约束的。

另外,(void *)0 不是左值,根据 6.5.4p5 的脚注 104:

强制转换不会产生左值。因此,强制类型转换与类型的非限定版本具有相同的效果。

【讨论】:

  • 感谢您和@John Bollinger 的进一步解释。还有一个问题,如果我把上面的改成(*a) = 5,会变成(* (&a[0])) = 5,而(* (&a[0]))是一个可修改的左值?
  • @5f3759df0x 没关系,因为一元 * 运算符产生一个左值,在这种情况下它的类型为 int
  • 我整天都被这个问题所困扰。如果我能给你一个拥抱,我可能会更好地表达我的感激之情。
  • @5f3759df0x 在这附近,我们通过 accepting an answer 进行操作。
【解决方案2】:

看起来像是从 int 数组到指向 int 数组的指针的转移类型,它变成了“可修改的左值”。

不,它没有。根据问题中已经包含的定义,a 被转换为类型为“指向int”的表达式不是左值。结果不是左值的后果之一是您不能分配给(整个)数组。

但我的 gcc 9.3.0 说:

error: assignment to expression with array type"

...这比“赋值给非左值的表达式”更容易理解。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-12
    • 1970-01-01
    • 1970-01-01
    • 2011-12-09
    • 1970-01-01
    • 2015-01-06
    相关资源
    最近更新 更多