繁体   English   中英

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

[英]lvalue required as increment operand - + unary operator

有人可以解释一下吗:

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

int main (void) {

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

   return 0;
}

应该是

将左值转换为右值示例

据此: 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

有人也可以解释一下吗?

+ 一元运算符如何工作?

我相信一元-更容易理解,因为它实际上“做了”一些“可见”的事情。 我的意思是,让int k = 5 then -k很简单——它将正值5变成负值-5 一元- “计算”它的操作数的负数。

内置的一元+只返回其操作数的值。 结束。 它什么也不做。 但是,应用一元运算符会对其参数执行标准中指定的提升 cppreference 运营商

内置的一元加号运算符返回其操作数的值。 它不是空操作的唯一情况是当操作数具有整数类型或无作用域枚举类型时,这会通过整数提升来更改,例如,它将 char 转换为 int 或者如果操作数受制于左值到右值,数组到指针或函数到指针的转换。

所以short值被提升为int 左值更改为右值。 数组类型衰减为指针。 并且 function 类型衰减为 function 指针。 Cppreference 值转换

Lvalue(“左值”)是您可以分配的东西。 在您的代码中i是一个变量,您可以i = 1将值1分配给i 并且2 + 2是一个值为4的右值(“正确的值”) - 你不能“分配”任何东西给2 + 2 ,它已经有了一个值。
+i是应用于i的一元+的结果 - i经历了 integer 提升和左值到右值转换,并且在这些转换之后,一元+操作的结果与i具有相同的值和类型。

摘自C11 第 6.5.3.3 段 - 第 2 项:

一元+运算符的结果是其(提升的)操作数的值。 对操作数执行 integer 提升,结果具有提升类型。

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

char a = 6;

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

由于从charinttype提升,操作数a大小1增长到4 操作数的,原封不动地返回。

来自评论: “将左值变成右值”,这就是我不明白的......

(+1)周围加括号的效果

int j = (+i)++;  

在这个表达式(+i)++中,括号()强制执行i (从表达式+ilvaluervalue的转换,在词法上紧随其后的是++运算符尝试增加i的值。 (从lexically ,因为这个表达式永远不会超过编译时进入运行时。)此时, i不再是左值,因此它不再是可赋值的,因此不能接受如果操作数是通常会发生的递增操作仍然是一个左值。

有趣的是,通过说明,以下表达式是完全合法的:

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

不是。

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

当我们使用左值来计算表达式时,它们被转换为它们的对象的值: x+3x中的任何值多产生三个。 在这个表达式中, x用于它的 相反,在x = 7; , x直接用作它的左值; 7 被写入 memory 中的字节,无论它们先前包含什么值。

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

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

脚注

1这就是左值可能指定 object 的原因: *p是左值,在编译期间被视为左值,但是,当程序执行时, p可能设置为 null 指针,因此*p实际上不会是 ZA8CFFDE6331BD59B26696C . 那将是程序中的错误,但它是运行时错误。

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

然而,一元+运算符的结果不是左值。 在这种情况下, +i的结果就是值0 ,所以表达式相当于写成0++ 您不能像不能写0 = 1一样将++运算符应用于0 - 您不能将值分配给值,只能通过左值将值分配给 object。

请注意,以下将起作用:

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

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

暂无
暂无

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

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