为什么我不能做++i++在类C语言中?

发布于 2024-08-06 17:06:07 字数 114 浏览 13 评论 0原文

半开玩笑半认真为什么我不能用类似 C 的语言(特别是 C#)执行 ++i++

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

Half jokingly half serious : Why can't I do ++i++ in C-like languages, specifically in C#?

I'd expect it to increment the value, use that in my expression, then increment again.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

七色彩虹 2024-08-13 17:06:07

尽管简短的回答“这不是左值”是正确,但这可能只是在回避问题。 为什么它不是左值?或者,正如我们在 C# 中所说的,一个变量

原因是因为鱼和熊掌不可兼得。从逻辑上理解:

首先,C# 中 ++ 运算符的含义,无论是后缀还是前缀,都是“取此变量的值,递增该值,将新值赋给该变量,并生成一个值作为结果”。作为结果生成的值是原始值或增量值,具体取决于它是后缀还是前缀。但无论哪种方式,你都会产生价值。

其次,变量的值始终是该变量的当前内容。 (对某些奇怪的线程场景进行模数处理,这些场景会让我们走得很远。)

我希望您同意这些是完全明智的规则。

现在应该清楚为什么 i++ 的结果不能是变量了,但如果不是,我先说清楚:

假设 i 是 10,i++ 的含义应该是“获取 i — 10 — 增量的值” it — 11 — 存储它 — i 现在是 11 — 并给出原始值作为结果 — 10”。所以当你说 print(i++) 时,它应该打印 10,并且 11 应该存储在 i 中。

现在假设 i++ 的含义是返回变量,而不是。你说 print(i++) 会发生什么?你得到 i 的值 — 10 — 增加它 — 11 — 存储它 — i 现在是 11 — 并将结果返回给变量。变量的当前值是多少? 11!这正是您不想打印的内容。

简而言之,如果 i++ 返回一个变量,那么它将执行与运算符的预期含义完全相反的操作!你的建议在逻辑上是不一致的,这就是为什么没有语言这样做的原因。

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.

舂唻埖巳落 2024-08-13 17:06:07

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

Short answer: i++ is not an "lvalue", so can't be the subject of an assignment.

£冰雨忧蓝° 2024-08-13 17:06:07

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

Because you care about a next programmer maintaining (or trying to re-write)your code, long after you're fired for defying popular conventions.

摘星┃星的人 2024-08-13 17:06:07

我测试了 (++i,i++) 作为解决方法:

#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         );
}

结果:


i:         0
(++i,i++): 1
i:         2

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
浊酒尽余欢 2024-08-13 17:06:07

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

Because the result of i++ isn't an lvalue.

踏雪无痕 2024-08-13 17:06:07

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

I believe that the increment(or decrement) operator needs an lvalue to assign to. However ++i is not an lvalue, it's an expression. Someone better versed in compilers might be able to clarify if there is any technical reason for this constraint.

强辩 2024-08-13 17:06:07

来自 C# 3.0 规范

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

此外,后自增表达式 (i++) 将首先计算,因为它的优先级高于预自增 (++i) 运算符。

From section 7.5.9 of the C# 3.0 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. If
the operand of a postfix increment or
decrement operation is a property or
indexer access, the property or
indexer must have both a get and a set
accessor. If this is not the case, a
compile-time error occurs.

Additionally, the post-increment expression (i++) would be evaluated first because it has a higher precedence than the pre-increment (++i) operator.

寻梦旅人 2024-08-13 17:06:07

来自 C#规范

后缀递增或递减运算的操作数必须是分类为变量、属性访问或索引器访问的表达式。运算结果是与操作数类型相同的

增量运算符只能应用于变量(和㏇)并且它返回一个值(而不是变量)。您无法将增量应用于值(仅仅因为没有可以将结果分配给的变量),因此在 C# 中您只能对变量进行一次增量。

对于C++来说,情况实际上有所不同。
根据 C++ 规范

前缀递增或递减是一个左值表达式

这意味着在 C++ 中,您可以对前缀增量或减量的结果调用增量。 IG 以下 C++ 代码 实际上是有效的:

#include <iostream>

using namespace std;

int main()
{
    int i = 13;

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

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

    return 0;
}

注意:术语 lvalue 仅在 C 和 C++ 中使用。并且为了 C 中的多样性,前缀增量的结果实际上是右值,因此您不能在 C 中增加增量。
C# 语言使用术语 variable_reference< /a> 类似的概念:

variable_reference 是一个被分类为变量的表达式。 Variable_reference 表示一个存储位置,可以访问它来获取当前值和存储新值。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文