简体   繁体   English

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

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

Can someone explain this:有人可以解释一下吗:

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

int main (void) {

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

   return 0;
}

which should be应该是

turning lvalue into rvalue example将左值转换为右值示例

according to this: What is the purpose of the unary plus (+) operator in C?据此: C 中的一元加号 (+) 运算符的目的是什么? , and gives error: lvalue required as increment operand . , 并给出错误: lvalue required as increment operand How does + unary operator work? +一元运算符如何工作?

also another usage I found in this site:我在这个网站上发现的另一种用法:

 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

can someone explain that as well?有人也可以解释一下吗?

How does + unary operator work? + 一元运算符如何工作?

I believe the unary - is simpler to understand, because it actually "does" something "visible".我相信一元-更容易理解,因为它实际上“做了”一些“可见”的事情。 I mean, having int k = 5 then -k is simple - it's turning the positive value 5 into a negative -5 .我的意思是,让int k = 5 then -k很简单——它将正值5变成负值-5 The unary - "calculates" the negative of it's operand.一元- “计算”它的操作数的负数。

The built-in unary + just returns the value of its operand.内置的一元+只返回其操作数的值。 The end.结束。 It does nothing.它什么也不做。 However, applying the unary operator performs promotions on its argument that are specified in the standard.但是,应用一元运算符会对其参数执行标准中指定的提升 From cppreference operators :cppreference 运营商

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, eg, it converts char to int or if the operand is subject to lvalue-to-rvalue, array-to-pointer, or function-to-pointer conversion.它不是空操作的唯一情况是当操作数具有整数类型或无作用域枚举类型时,这会通过整数提升来更改,例如,它将 char 转换为 int 或者如果操作数受制于左值到右值,数组到指针或函数到指针的转换。

So short value is promoted to int .所以short值被提升为int Lvalues are changed to rvalues.左值更改为右值。 Array types decay to a pointer.数组类型衰减为指针。 And a function types decay to a function pointers.并且 function 类型衰减为 function 指针。 Cppreference value transformations . Cppreference 值转换

Lvalue ("left value") is something you can assign to. Lvalue(“左值”)是您可以分配的东西。 In your code i is a variable, you can i = 1 assign value 1 to i .在您的代码中i是一个变量,您可以i = 1将值1分配给i And 2 + 2 is an rvalue ("right value") with value 4 - you can't "assign" anything to 2 + 2 , it already has a value.并且2 + 2是一个值为4的右值(“正确的值”) - 你不能“分配”任何东西给2 + 2 ,它已经有了一个值。
+i is the result of unary + applied to i - i undergoes integer promotions and lvalue-to-rvalue conversion and the result of the unary + operation has the same value and type as i after those transformations. +i是应用于i的一元+的结果 - i经历了 integer 提升和左值到右值转换,并且在这些转换之后,一元+操作的结果与i具有相同的值和类型。

Excerpt from C11 para 6.5.3.3 - item 2:摘自C11 第 6.5.3.3 段 - 第 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.对操作数执行 integer 提升,结果具有提升类型。

So basically, the effect is almost always a no-op with the exceptions of int type promotions to its operands.所以基本上,效果几乎总是无操作,除了对其操作数的int类型提升。 eg,例如,

char a = 6;

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

Where because of the type promotion from char to int , the size of the operand a grew from 1 to 4 .由于从charinttype提升,操作数a大小1增长到4 The value of the operand, is returned unchanged.操作数的,原封不动地返回。

From comments: "turning lvalue into rvalue", that is what I do not understand ...来自评论: “将左值变成右值”,这就是我不明白的......

The effect of placing parenthesis around (+1)(+1)周围加括号的效果

int j = (+i)++;  

In this expression (+i)++ , the order of precedence is forced by the parenthesis () to perform the transformation of i (from the expression +i ) from being an lvalue to an rvalue , lexically followed by ++ operator in an attempt to increment the value of i .在这个表达式(+i)++中,括号()强制执行i (从表达式+ilvaluervalue的转换,在词法上紧随其后的是++运算符尝试增加i的值。 ( lexically because this expression will never live beyond compile-time into run-time.) At this point, i is no longer an lvalue, consequently it is no longer assignable, therefore cannot accept the increment operation that would normally happen if the operand was still an lvalue. (从lexically ,因为这个表达式永远不会超过编译时进入运行时。)此时, i不再是左值,因此它不再是可赋值的,因此不能接受如果操作数是通常会发生的递增操作仍然是一个左值。

It is interesting to note by way of illustration that the following expressions are perfectly legal:有趣的是,通过说明,以下表达式是完全合法的:

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`.  

The unary operator + turns an lvalue into an rvalue .一元运算符+lvalue转换为rvalue
The terms can essentially be thought of as assignable and not assignable respectively.这些术语基本上可以分别被认为是可转让的和不可转让的。

As also shown by these expressions:这些表达式也表明:

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

is legal.是合法的。 But:但:

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

is not.不是。

An lvalue is an expression that potentially designates an object (bytes in memory).左值是可能指定 object(内存中的字节)的表达式。 The most common form of lvalue is simply a name: Given int x , float y , or char z[10] , then x , y , and z are lvalues.左值最常见的形式只是一个名称:给定int xfloat ychar z[10] ,则xyz是左值。 Another form of lvalue is the result of unary * : Given double *p;左值的另一种形式是一元*的结果:给定double *p; , then *p is an lvalue. , 那么*p是一个左值。 1 1

When we use lvalues to compute expressions, they are turned into the values of their objects: x+3 produces three more than whatever value is in x .当我们使用左值来计算表达式时,它们被转换为它们的对象的值: x+3x中的任何值多产生三个。 In this expression x is used for its value .在这个表达式中, x用于它的 In contrast, in x = 7;相反,在x = 7; , x is used directly as its lvalue; , x直接用作它的左值; 7 is written to the bytes in memory, regardless of what value they previously contained. 7 被写入 memory 中的字节,无论它们先前包含什么值。

Since the C standard must specify how compilers behave in technical details, it specifies that, when an lvalue is used in an expression in a place where we want its value, that lvalue is converted to a value.由于 C 标准必须指定编译器在技术细节中的行为方式,因此它规定,当在表达式中我们想要其值的地方使用左值时,该左值将转换为值。 To emphasize that this result is just a number or similar thing and is no longer a reference to memory, it may be called an rvalue .为了强调这个结果只是一个数字或类似的东西,不再是对 memory 的引用,它可能被称为rvalue

Unary + is an operator.一元+是一个运算符。 When applied to an arithmetic value, it produces the same value.当应用于算术值时,它会产生相同的值。 However, it only produces a value, not an lvalue.但是,它只产生一个值,而不是一个左值。 So applying + to an lvalue produces an rvalue.因此,将+应用于左值会产生右值。

Footnote脚注

1 This is why an lvalue potentially designates an object: *p is an lvalue and is treated as such during compilation, but, when the program is executing, p might be set to a null pointer, so *p would not actually be an object. 1这就是左值可能指定 object 的原因: *p是左值,在编译期间被视为左值,但是,当程序执行时, p可能设置为 null 指针,因此*p实际上不会是 ZA8CFFDE6331BD59B26696C . That would be an error in the program, but it is a run-time error.那将是程序中的错误,但它是运行时错误。

The ++ operator expects its operand to be an lvalue - basically, an expression that can designate an object (in the C sense, a chunk of memory that can be used to store a value). ++运算符期望它的操作数是一个左值- 基本上,一个可以指定 object 的表达式(在 C 意义上,一块 memory 可以用来存储一个值)。

The result of the unary + operator, however, is not an lvalue.然而,一元+运算符的结果不是左值。 In this case, the result of +i is just the value 0 , so the expression is equivalent to writing 0++ .在这种情况下, +i的结果就是值0 ,所以表达式相当于写成0++ You can't apply the ++ operator to 0 the same way you can't write 0 = 1 - you cannot assign a value to a value, you can only assign a value to an object through an lvalue.您不能像不能写0 = 1一样将++运算符应用于0 - 您不能将值分配给值,只能通过左值将值分配给 object。

Note that following would work:请注意,以下将起作用:

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

You're applying the + operator to the result of i++ , which would be 0 (the postfix ++ evaluates to the current value of i , and as a side effect increments i ).您将+运算符应用于i++的结果,即0 (后缀++计算为i当前值,并且作为副作用递增i )。 The result of i++ is not an lvalue either, but + does not require its operand to be an lvalue. i++的结果也不是左值,但+并不要求其操作数是左值。

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

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