29

半开玩笑半严肃为什么我不能++i++用类 C 语言,特别是 C#?

我希望它增加值,在我的表达式中使用它,然后再次增加。

4

8 回答 8

85

Though the short answer "it's not an lvalue" is correct, that's perhaps just begging the question. Why isn't it an lvalue? Or, as we say in C#, a variable.

The reason is because you cannot have your cake and eat it too. Work it out logically:

First off, the meaning of a ++ operator in C#, whether postfix or prefix, is "take the value of this variable, increment the value, assign the new value to the variable, and produce a value as a result". The value produced as the result is either the original value or the incremented value, depending on whether it was a postfix or a prefix. But either way, you produce a value.

Second, the value of a variable is always the current contents of that variable. (Modulo certain bizarre threading scenarios that would take us far afield.)

I hope you agree that these are perfectly sensible rules.

Now it should be clear why the result of i++ cannot be a variable, but in case it isn't, let me make it clear:

Suppose i is 10. The meaning of i++ should be "get the value of i — 10 — increment it — 11 — store it — i is now 11 — and give the original value as the result — 10". So when you say print(i++) it should print 10, and 11 should be stored in i.

Now suppose the meaning of i++ is to return the variable, not the value. You say print(i++) and what happens? You get the value of i — 10 — increment it — 11 — store it — i is now 11 — and give the variable back as a result. What's the current value of the variable? 11! Which is exactly what you DON'T want to print.

In short, if i++ returned a variable then it would be doing exactly the opposite of the intended meaning of the operator! Your proposal is logically inconsistent, which is why no language does it that way.

于 2009-10-02T18:47:56.713 回答
58

简短回答:i++不是“左值”,因此不能成为分配的主题。

于 2009-10-02T18:22:49.990 回答
18

因为您关心下一个程序员维护(或尝试重写)您的代码,在您因违反流行惯例而被解雇很久之后。

于 2009-10-02T18:22:34.547 回答
8

I tested (++i,i++) as a workaround:

#include <stdio.h> 

int main(){
  int i=0;

  printf(" i:         %i\n", i         );
  printf(" (++i,i++): %i\n", (++i,i++) );
  printf(" i:         %i\n", i         );
}

Result:


i:         0
(++i,i++): 1
i:         2
于 2009-10-02T19:06:08.297 回答
6

因为结果i++不是左值。

于 2009-10-02T18:26:42.950 回答
3

我相信增量(或减量)运算符需要一个左值来分配。但是 ++i 不是左值,它是一个表达式。精通编译器的人可能能够澄清这种约束是否有任何技术原因。

于 2009-10-02T18:23:01.753 回答
3

C# 3.0 规范的第 7.5.9 节:

后缀递增或递减操作的操作数必须是分类为变量、属性访问或索引器访问的表达式。运算的结果是与操作数相同类型的值。如果后缀递增或递减操作的操作数是属性或索引器访问,则属性或索引器必须同时具有 get 和 set 访问器。如果不是这种情况,则会发生编译时错误。

此外,将首先评估后增量表达式 ( ),因为它比前增量 ( ) 运算符i++具有更高的优先级。++i

于 2009-10-02T18:35:32.913 回答
0

From C# specification:

The operand of a postfix increment or decrement operation must be an expression classified as a variable, a property access, or an indexer access. The result of the operation is a value of the same type as the operand.

An increment operator can only be applied to a variable (and ㏇) and it returns a value (not a variable). You cannot apply increment to a value (simply because there is no variable to assign the result to) so in C# you can increment a variable only once.

The situation is actually different for C++. According to C++ specification:

prefix increment or decrement is an lvalue expression

which means that in C++ you can call increment on the result of prefix increment or decrement. I.g. the following C++ code is actually valid:

#include <iostream>

using namespace std;

int main()
{
    int i = 13;

    (--i)++;
    cout<<i<<endl;

    (++i)--;
    cout<<i<<endl;

    return 0;
}

NB: The term lvalue is used in C and C++ only. And for the sake of diversity in C the result of prefix increment is actually rvalue so you can't increment increment in C.
C# language uses term variable_reference for a similar concept:

A variable_reference is an expression that is classified as a variable. A variable_reference denotes a storage location that can be accessed both to fetch the current value and to store a new value.

于 2021-07-14T11:49:39.737 回答