在C++中,前置自增运算符返回左值,因为自增后的对象本身被返回,而不是其副本。
但在C中,它返回右值。为什么?
C语言没有引用(references)的概念。在C++中,++i
会返回对的引用(lvalue),而在C中它将返回的副本(增加后的值)。
C99 6.5.3.1/2:
前缀++操作符的操作数的值递增。结果是递增后操作数的新值。表达式++E等效于(E+=1)。
“表达式的值” <=> 右值
然而,出于历史原因,我认为“C语言中没有引用的概念”可能是一个可能的原因。
++i
并不“返回”副本,也没有副本。++i
求值为i
的新值。除非您在生成副本的较大表达式中使用它,否则不会生成副本。 - CB Baileyi=j
也会评估为一个值。尝试取地址(i=j)
,你肯定会得到一个错误。 - Prasoon Saurav*(++i,&i) = 10;
是可行的。你可以定义一个宏#define PREINC(x) *(++(x),&(x))
。 (我一个小时前的评论有误,现已删除。) - Aaron McDaidint x
,在C++中decltype(*&x)
是int&
。但是*&x
在C++和C中都是左值,尽管C没有int&
。因此,在特殊情况下,C支持表达式外的左值,因此没有引用不是不支持前缀递增的好解释,这是一个薄弱的论点。 - oblitum名称“lvalue”最初来自赋值表达式E1 = E2,其中要求左操作数E1为(可修改的)左值。它可能更好地被认为代表一个对象的“定位器值”。在这个国际标准中,有时所谓的“rvalue”被描述为“表达式的值”。
希望这解释了为什么在C中,++i
返回rvalue。
i
的类型如此定义为Index
,则您始终可以编写i++++++++
或++++++i
。
*&x
被称为表达式,并且是一个lvalue:https://dev59.com/questions/i2445IYBdhLWcg3wkLBG#YfUYoYgBc1ULPQZFY4WT - oblitumint *p = &someAggregateArr[i++].member;
,则子表达式someAggregateArr[i++].member
应该产生一个“定位器值”,它标识了someAggregateArr[5].member
,尽管后者不是代码中出现的任何表达式。 - supercat就我个人而言,我无法想象出使用预增变量作为lvalue可能产生的任何有用语句。在C++中,由于运算符重载的存在,我可以。您是否有具体的例子,说明由于此限制而无法在C中执行某些操作?
++i
的结果作为lvalue的方式都会因缺乏序列点而导致未定义行为。因此,禁止它的语法并没有太大损失,尽管myfunc(&(++i))
是可以的,并且有时很有用。还要注意,在C语言中,(++i,i)
等同于如果它评估为lvalue的话,++i
将是什么,因此即使您需要它,它仍然不是很重要。 - Steve Jessop++i %= bufsize
。(我承认,你可以用其他方式编写这个语句。) - moooeeeepx=(x+y)&z;
的运算符有很多用途,但是在使用z
进行掩码处理之前存储中间值并没有太多好处。 - supercat