为什么'bicrement'不可能这样?

时间:2012-09-01 20:46:55

标签: language-agnostic increment

为什么这不可能?

int c = 0;
++c++;

或者在PHP中:

$c = 0;
++$c++;

我希望它将变量c递增2,或者做一些奇怪的事情,但是编译时会出错。我试图提出一个理由但却没有得到任何理由......我的理由是:

  1. 编译器读取++
  2. 它读取变量
  3. 它执行的任何操作都可以使变量的值增加,然后在执行应用程序时返回
  4. 遇到另一个++
  5. 它使用前一个变量,以便在递增值
  6. 之前返回它
  7. 这是令人困惑的地方:它是使用变量c,还是尝试读取(++ c)返回的值?或者,既然你只能做varname ++(而不是2 ++),它会看到(++ c)作为指针,然后尝试读取那个内存位置吗?无论它做什么,为什么会出现编译错误?或者是预防错误,因为编译器的程序员知道它不会做任何有用的事情吗?
  8. 我并不是真的想要使用它,当然不是仅仅用于一次性使用的代码,但我只是好奇。

3 个答案:

答案 0 :(得分:7)

出于同样的原因你不能这样做:

c++ = 5;

返回一个值,该值不能修改也不能分配给。这也不是运行时错误 - 这是编译错误。 (Like this one.)

返回引用也没有意义,因为那时:

$a = 1;
$b = $a++; // How can it be a reference if b should be 1 and a should be 2?

答案 1 :(得分:3)

这不是必然与语言无关,尽管我看到一种与之不同的语言会有点惊讶。

在C中(因此我假设在所有基于C的非烦人语言中),运算符优先级意味着你的表达式等同于++(c++)。根据您的分步,您希望它等同于(++c)++,但事实并非如此。 Postfix ++“绑定得比前缀++更紧密。”

就像每个人都说的那样,表达式c++会产生一个值,而不是一个可修改的对象(C中引用一个对象的表达式称为左值)。这是必要的,因为对象c不再保存表达式求值的值 - 没有c++可以引用的对象。

在C ++中(不要与c++混淆!),++c 是一个左值。它引用了对象c,它现在具有新值。

所以在C ++中(++c)++在语法上是正确的。如果c的类型为int,它恰好有未定义的行为(至少,在C ++ 03中它做了:C ++ 11定义了一些以前未定义的东西,我不是最新的更改)。

因此,如果您想象(或继续发明)类似C ++的语言,其中运算符优先级符合您的预期,那么您可以安排++c++有效。据推测,它会增加c两次,并评估旧值和新值之间的值。这种想象的语言在某种意义上是“烦人的”,因为它与C ++略有不同,后者往往会让人感到困惑。

如果++c++是用户定义类型的一个实例,它使两个增量运算符都重载,那么

c在C ++中也是有效的。原因是用户定义类型的右值是对象(“临时对象”),并且可以修改。但是一旦表达式被评估,临时就会被破坏,修改就会丢失。

答案 2 :(得分:1)

解释这一点的另一种方法是++运算符仅在左值上运算。但是当你将它们组合起来时,它被解析为++(c++)(++c)++ - 在任何一种情况下,括号外的运算符参数都是rvalue(c之前或之后的值增量),而不是左值。