逗号运算符没有副作用吗?

发布于 2024-12-10 00:56:45 字数 126 浏览 1 评论 0原文

例如,对于这样的语句:

c += 2, c -= 1

c += 2 是否总是首先被求值,并且第二个表达式 c-= 1 中的 c 是否总是从表达式 c += 2 更新值?

For example for such statement:

c += 2, c -= 1

Is it true that c += 2 will be always evaluated first, and c in second expression c-= 1 will always be updated value from expression c += 2?

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

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

发布评论

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

评论(5

捶死心动 2024-12-17 00:56:45

是的,只要该逗号是非重载的逗号运算符,它就受到标准的保证。引用 n3290 §5.18:

逗号运算符从左到右分组。

<块引用>

表达式:
赋值表达式
表达式,赋值表达式

一对用逗号分隔的表达式从左到右计算;左边的表达式是一个被丢弃的表达式
值表达式(第 5 条)83。与左侧表达式相关的每个值计算和副作用
在与正确表达式相关的每个值计算和副作用之前排序。类型
和结果的值是右操作数的类型和值;结果属于相同的值类别
作为其右操作数,如果其右操作数是左值和位域,则为位域。

以及相应的脚注:

83 但是,重载逗号运算符的调用是普通函数调用;因此,对其论点的评估
表达式相对于彼此而言是无序的(参见 1.9)。

因此,这仅适用于非重载的逗号运算符。

函数参数之间的 , 不是逗号运算符。这条规则在那里也不适用。

对于C++03,情况类似:

逗号运算符从左到右分组。

<块引用>

表达式:
赋值表达式
表达式,赋值表达式

一对用逗号分隔的表达式从左到右计算,左侧表达式的值为
被丢弃。左值到右值 (4.1)、数组到指针 (4.2) 和函数到指针 (4.3) 标准转换
sions 不适用于左侧表达式。 左侧表达式的所有副作用 (1.9),除了
临时变量的销毁 (12.2) 在评估正确表达式之前执行。
类型和
结果的值是右操作数的类型和值;如果其右操作数是,则结果是左值。

但限制是相同的:不适用于重载的逗号运算符或函数参数列表。

Yes, it is guaranteed by the standard, as long as that comma is a non-overloaded comma operator. Quoting n3290 §5.18:

The comma operator groups left-to-right.

expression:
assignment-expression
expression , assignment-expression

A pair of expressions separated by a comma is evaluated left-to-right; the left expression is a discarded-
value expression (Clause 5)83. Every value computation and side effect associated with the left expression
is sequenced before every value computation and side effect associated with the right expression. The type
and value of the result are the type and value of the right operand; the result is of the same value category
as its right operand, and is a bit-field if its right operand is a glvalue and a bit-field.

And the corresponding footnote:

83 However, an invocation of an overloaded comma operator is an ordinary function call; hence, the evaluations of its argument
expressions are unsequenced
relative to one another (see 1.9).

So this holds only for the non-overloaded comma operator.

The , between arguments to a function are not comma operators. This rule does not apply there either.

For C++03, the situation is similar:

The comma operator groups left-to-right.

expression:
assignment-expression
expression , assignment-expression

A pair of expressions separated by a comma is evaluated left-to-right and the value of the left expression is
discarded. The lvalue-to-rvalue (4.1), array-to-pointer (4.2), and function-to-pointer (4.3) standard conver-
sions are not applied to the left expression. All side effects (1.9) of the left expression, except for the
destruction of temporaries (12.2), are performed before the evaluation of the right expression.
The type and
value of the result are the type and value of the right operand; the result is an lvalue if its right operand is.

Restrictions are the same though: does not apply to overloaded comma operators, or function argument lists.

淡笑忘祈一世凡恋 2024-12-17 00:56:45

是的,逗号运算符保证语句按从左到右的顺序计算,并且返回值是计算的最右边的语句。

但请注意,某些上下文中的逗号不是逗号运算符。例如,对于函数参数列表,不能保证上述情况。

Yes, the comma operator guarantees that the statements are evaluated in left-to-right order, and the returned value is the evaluated rightmost statement.

Be aware, however, that the comma in some contexts is not the comma operator. For example, the above is not guaranteed for function argument lists.

星星的軌跡 2024-12-17 00:56:45

是的,在 C++ 中,逗号运算符是一个序列点,这些表达式将按照它们的写入顺序进行计算。请参阅当前工作草案中的5.18

[snip] 从左到右计算。 [截图]

我觉得你的问题缺乏对“副作用”含义的解释。 C++ 中的每个语句都允许有副作用,重载的逗号运算符也是如此。

为什么你写的语句在函数调用中无效?

这都是关于序列点的。在 C++ 和 C 中,禁止在两个序列点之间修改两次值。如果您的示例真正使用运算符,则每个自分配都位于其自己的序列点内。如果您像这样使用它 foo(c += 2, c -= 2) 则评估顺序是未定义的。我实际上不确定第二种情况是否是未定义的行为,因为我不知道参数列表是一个还是多个序列点。我应该问这个问题。

Yes, in C++ the comma operator is a sequence point and those expression will be evaluated in the order they are written. See 5.18 in the current working draft:

[snip] is evaluated left-to-right. [snip]

I feel that your question is lacking some explanation as to what you mean by "side effects". Every statement in C++ is allowed to have a side effect and so is an overloaded comma operator.

Why is the statement you have written not valid in a function call?

It's all about sequence points. In C++ and C it is forbidden to modify a value twice inside between two sequence points. If your example truly uses operator, every self-assignment is inside its own sequence point. If you use it like this foo(c += 2, c -= 2) the order of evaluation is undefined. I'm actually unsure if the second case is undefined behaviour as I do not know if an argument list is one or many sequence points. I ought to ask a question about this.

嗫嚅 2024-12-17 00:56:45

它应该始终从左到右计算,因为这是逗号运算符的定义:
链接

It should be always evaluated from left to right, as this is the in the definition of the comma operator:
Link

多情出卖 2024-12-17 00:56:45

你有两个问题。

第一个问题:“逗号运算符没有副作用吗?”

答案是否定的。逗号运算符自然有利于编写具有副作用的表达式,而故意编写具有副作用的表达式正是该运算符的常用用途。例如,在 while (cin >> str, str != "exit") 中,输入流的状态发生了改变,这是有意的副作用。

但也许你并不是指计算机科学意义上的副作用,而是某种特殊意义上的副作用。

你的第二个问题:“例如,对于这样的语句:c += 2, c -= 1 是否总是先计算 c += 2,然后在第二个表达式 c-= 1 中计算 c总是会从表达式 c += 2 更新值?”

对于语句或表达式,答案是肯定的,除非逗号运算符被重载(非常不寻常)。但是,像 c += 2, c -= 1 这样的序列也可以出现在参数列表中,在这种情况下,您得到的不是表达式,逗号也不是序列运算符,并且评估的顺序没有定义。在 foo(c += 2, c -= 1) 中,逗号不是逗号运算符,但在 foo((c += 2, c -= 1)) 中> 是的,所以可能要注意函数调用中的括号。

You've got two questions.

The first question: "Is comma operator free from side effect?"

The answer to this is no. The comma operator naturally facilitates writing expressions with side effects, and deliberately writing expressions with side effects is what the operator is commonly used for. E.g., in while (cin >> str, str != "exit") the state of the input stream is changed, which is an intentional side effect.

But maybe you don't mean side-effect in the computer science sense, but in some ad hoc sense.

Your second question: "For example for such statement: c += 2, c -= 1 Is it true that c += 2 will be always evaluated first, and c in second expression c-= 1 will always be updated value from expression c += 2?"

The answer to this is yes in the case of a statement or expression, except when the comma operator is overloaded (very unusual). However, sequences like c += 2, c -= 1 can also occur in argument lists, in which case, what you've got is not an expression, and the comma is not a sequence operator, and the order of evaluation is not defined. In foo(c += 2, c -= 1) the comma is not a comma operator, but in foo((c += 2, c -= 1)) it is, so it may pay to pay attention to the parentheses in function calls.

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