简体   繁体   English

在 C 中,每个带有“类型数组”的表达式将始终转换为“指向类型数组的指针”

[英]Every expression with "array of type" will always be converted to "pointer to array of type" in C

Example code:示例代码:

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

According to 6.5.1 Primary expressions根据6.5.1 主要表达式

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

and 6.3.2.1 Lvalues, arrays, and function designators6.3.2.1 左值、arrays 和 function 指示符

An lvalue is an expression with an object type or an incomplete type other than void;左值是具有 object 类型或 void 以外的不完整类型的表达式; if an lvalue does not designate an object when it is evaluated, the behavior is undefined.如果左值在评估时未指定 object,则行为未定义。 When an object is said to have a particular type, the type is specified by the lvalue used to designate the object.当 object 被称为具有特定类型时,该类型由用于指定 object 的左值指定。 A modifiable lvalue is an lvalue that does not have array type, does not have an incomplete type, does not have a const-qualified type, and if it is a structure or union, does not have any member (including, recursively, any member or element of all contained aggregates or unions) with a const-qualified type.可修改的左值是没有数组类型、没有不完整类型、没有 const 限定类型,并且如果它是结构或联合,则没有任何成员(包括递归地,任何成员或所有包含的聚合或联合的元素)具有 const 限定类型。

We know both a and (void *) 0 are l-value expression and a has a array of type.我们知道a(void *) 0都是左值表达式,并且a有一个类型的数组。

If we look following definition:如果我们看下面的定义:

Except when it is the operand of the sizeof operator or the unary & operator, or is a string literal used to initialize an array, an expression that has type ''array of type'' is converted to an expression with type ''pointer to type'' that points to the initial element of the array object and is not an lvalue.除非它是 sizeof 运算符或一元 & 运算符的操作数,或者是用于初始化数组的字符串字面量,否则类型为 ''array of type'' 的表达式将转换为类型为 ''pointer to type'' 指向数组 object 的初始元素并且不是左值。 If the array object has register storage class, the behavior is undefined.如果数组 object 具有寄存器存储 class,则行为未定义。

Looks like type of a transfer from array of int to pointer to array of int , it becomes "modifiable lvalue".看起来像是从array of intpointer to array of int的指针a传输类型,它变成了“可修改的左值”。 But my gcc 9.3.0 said:但我的 gcc 9.3.0 说:

error: assignment to expression with array type"

I am confused.我很困惑。

The part you missed is section 6.5.16p2 regarding constraints on Assignment Operators:您错过的部分是关于赋值运算符约束的第 6.5.16p2 节:

An assignment operator shall have a modifiable lvalue as its left operand赋值运算符应该有一个可修改的左值作为它的左操作数

An array is not a modifiable lvalue, therefore it's a constraint violation to have it on the left side of an assignment.数组不是可修改的左值,因此将它放在赋值的左侧是违反约束的。

Also, (void *)0 is not an lvalue, as per footnote 104 on 6.5.4p5:此外, (void *)0不是左值,根据 6.5.4p5 上的脚注 104:

A cast does not yield an lvalue.强制转换不会产生左值。 Thus, a cast to a qualified type has the same effect as a cast to the unqualified version of the type.因此,强制类型转换与类型的非限定版本具有相同的效果。

Looks like type of a transfer from array of int to pointer to array of int, it becomes "modifiable lvalue".看起来像是从 int 数组到指向 int 数组的指针的传输类型,它变成了“可修改的左值”。

No, it doesn't.不,它没有。 Per the definition already included in the question, a is converted to an expression of type "pointer to int " that is not an lvalue .根据问题中已经包含的定义, a被转换不是lvalue的“pointer to int ”类型的表达式。 Among the consequences of the result not being an lvalue is that you cannot assign to (whole) arrays.结果不是左值的后果之一是您不能分配给(整个)arrays。

But my gcc 9.3.0 said:但我的 gcc 9.3.0 说:

 error: assignment to expression with array type"

... which is easier to understand than "assignment to an expression that is not an lvalue". ...这比“分配给不是左值的表达式”更容易理解。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM