需要左值作为递增操作数 - + 一元运算符

lvalue required as increment operand - + unary operator

谁能解释一下:

#include <stdio.h>
#include <stdlib.h>

int main (void) {

   int i = 0,j;
   j=(+i)++;

   return 0;
}

应该是

turning lvalue into rvalue example

据此:What is the purpose of the unary plus (+) operator in C?, 并给出错误:lvalue required as increment operand+ 一元运算符如何工作?

还有我在此站点中发现的另一种用法:

 little known: The unary plus operator can be used as an "decay
 operator": Given int a[10]; int b(void);, then +a is an int pointer
 and +b is a function pointer. Useful if you want to pass it to a
 template accepting a reference

有人也可以解释一下吗?

摘自 C11 para 6.5.3.3 - item 2:

The result of the unary + operator is the value of its (promoted) operand. The integer promotions are performed on the operand, and the result has the promoted type.

所以基本上,效果几乎总是 无操作 除了对其操作数的 int 类型提升之外。例如,

char a = 6;

size_t size_pre_promotion = sizeof(a);
size_t size_post_promotion = sizeof(+a);

由于从 charinttype 提升, 操作数 a 大小从14。操作数的 value 原样返回。

来自评论: "turning lvalue into rvalue",就是我不明白...

(+1)

两边加括号的效果
int j = (+i)++;  

在此表达式 (+i)++ 中,括号 () 强制执行优先顺序以执行 i(来自表达式 +i)的转换lvaluervalue,词法后跟 ++ 运算符,试图增加 i 的值。 ( lexically 因为这个表达式永远不会超出编译时间进入 运行 时间。)在这一点上, i 不再是左值,因此它不再是可分配的,因此不能接受如果操作数仍然是左值通常会发生的 increment 操作。

有趣的是,下面的表达式是完全合法的:

int j = (+i);//Not attempting to assign value (increment) the operand
             //so the _value_ returned from the operand is successfully assigned
             //to the lvalue `j`;


int j = +i++;//Assigns the i + 1 to j
        //in this case the `++` adds `1` to the operand, then the `+` unary operator returns the incremented value (essentially a no-op at this point),  which in turn is assigned to the _lvalue_ `j`.  

一元运算符 +lvalue 转换为 rvalue
这些术语基本上可以分别被认为是 可分配不可分配

这些表达式也表明:

int j;
&j; //address of an lvalue

是合法的。但是:

&(+j);//cannot _take_ the address of an rvalue

不是。

How does + unary operator work?

我相信一元 - 更容易理解,因为它实际上 "does" 是 "visible"。我的意思是,让 int k = 5 然后 -k 很简单——它将正值 5 变成负值 -5。一元 - "calculates" 它的操作数的负数。

内置一元+只是returns其操作数的值。结束。它什么都不做。但是,应用一元运算符会执行 promotions on its argument that are specified in the standard. From cppreference operators:

The built-in unary plus operator returns the value of its operand. The only situation where it is not a no-op is when the operand has integral type or unscoped enumeration type, which is changed by integral promotion, e.g, it converts char to int or if the operand is subject to lvalue-to-rvalue, array-to-pointer, or function-to-pointer conversion.

因此 short 值提升为 int。左值变为右值。数组类型退化为指针。函数类型衰减为函数指针。 Cppreference value transformations.

左值 ("left value") 是您可以分配给的东西。在你的代码中 i 是一个变量,你可以 i = 1 将值 1 赋值给 i2 + 2 是一个右值 ("right value"),其值为 4 - 你不能 "assign" 任何 2 + 2 , 它已经有一个值。
+i 是一元 + 应用于 i 的结果 - i 经历了整数提升和左值到右值的转换以及一元 + 操作的结果在这些转换后与 i 具有相同的值和类型。

lvalue 是一个可能指定对象(内存中的字节)的表达式。最常见的左值形式只是一个名称:给定 int xfloat ychar z[10],然后 xyz是左值。左值的另一种形式是一元*的结果:给定double *p;,那么*p是一个左值。1

当我们使用左值来计算表达式时,它们会变成它们对象的值:x+3x 中的任何值多产生三个。在此表达式中,x 用于其 。相比之下,在x = 7;中,直接使用x作为它的左值; 7 被写入内存中的字节,无论它们之前包含什么值。

由于 C 标准必须在技术细节上指定编译器的行为方式,因此它指定,当在表达式中我们需要其值的地方使用左值时,该左值将转换为值。为了强调这个结果只是一个数字或类似的东西,不再是对内存的引用,它可能被称为rvalue.

一元 + 是一个运算符。当应用于算术值时,它会产生相同的值。但是,它只产生一个值,而不是左值。因此,将 + 应用于左值会产生右值。

脚注

1 这就是为什么一个左值 可能 指定一个对象:*p 是一个左值并且在编译,但是,当程序执行时,p 可能被设置为空指针,因此 *p 实际上不是一个对象。那将是程序中的错误,但它是 运行 时间错误。

++ 运算符期望它的操作数是一个 左值 - 基本上,一个可以指定对象的表达式(在 C 意义上,一块内存可用于存储值)。

然而,一元运算符 + 的结果不是左值。在这种情况下,+i 的结果只是值 0,因此表达式等同于写 0++。您不能将 ++ 运算符应用于 0,就像您不能编写 0 = 1 一样 - 您不能将值分配给一个值,您只能将一个值分配给一个对象一个左值。

请注意,以下会起作用:

j = +(i++); // or just +i++, precedence is the same

您将 + 运算符应用于 i++ 的结果,即 0(后缀 ++ 的计算结果为 i 的当前 值,并且作为 副作用 递增 i)。 i++ 的结果也不是左值,但 + 不要求其操作数是左值。