(--i == i++) 是未定义的行为吗?

发布于 2024-10-21 19:01:28 字数 415 浏览 4 评论 0原文

这个问题与我之前的问题相关。我得到的答案是“这是一种未定义的行为。”

请任何人解释一下:

  • 什么是未定义的行为?
  • 我怎么知道我的代码有未定义的行为?

示例代码:

int i = 5;
if (--i == i++)         
   Console.WriteLine("equal and i=" + i);           
else
   Console.WriteLine("not equal and i=" + i);

//output: equal and i=6

this question is related to my previous problem. The answer I got was "It is an Undefined behavior."

Please anyone explain:

  • What is an undefined behavior?
  • how can I know my code has an undefined behavior?

Example code:

int i = 5;
if (--i == i++)         
   Console.WriteLine("equal and i=" + i);           
else
   Console.WriteLine("not equal and i=" + i);

//output: equal and i=6

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

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

发布评论

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

评论(8

苍风燃霜 2024-10-28 19:01:28

什么是未定义行为?

它很简单,是适当的语言规范没有明确定义的任何行为。某些规范会将某些事物列为显式未定义,但实际上任何未描述为已定义的事物都是未定义的。

我怎么知道我的代码有未定义的行为?

希望你的编译器会警告你 - 如果情况并非如此,你需要阅读语言规范并了解所有有趣的角落情况和角落。导致此类问题的裂缝。

出去要小心!

What is an Undefined-Behaviour?

It's quite simply any behaviour that is not specifically defined by the appropriate language specification. Some specs will list certain things as explicitly undefined, but really anything that's not described as being defined is undefined.

how can I know my code has an undefined behavior?

Hopefully your compiler will warn you - if that's not the case, you need to read the language specification and learn about all the funny corner cases and nooks & crannies that cause these sorts of problems.

Be careful out there!

长伴 2024-10-28 19:01:28

它在 C 中未定义,但在 C# 中定义良好:

来自 C# (ECMA-334) 规范“运算符优先级和结合性”部分 (§14.2.1):

  • 除了赋值运算符和空合并运算符之外,所有
    二元运算符是左-
    关联性,意味着操作
    从左到右执行。
    [示例:x + y + z 计算为 (x + y) + z。结束示例]

因此,首先评估 --i,将 i 更改为 4,然后评估为 4。然后 i++ 评估,更改 i 为 5,但计算结果为 4。

It's undefined in C, but well-defined in C#:

From C# (ECMA-334) specification "Operator precedence and associativity" section (§14.2.1):

  • Except for the assignment operators and the null coalescing operator, all
    binary operators are left-
    associative, meaning that operations
    are performed from left to right.
    [Example: x + y + z is evaluated as (x + y) + z. end example]

So --i is evaluated first, changing i to 4 and evaluating to 4. Then i++ is evaluating, changing i to 5, but evaluating to 4.

烟酉 2024-10-28 19:01:28

是的,该表达式也是未定义的行为(在 C 和 C++ 中)。有关规则的一些信息,请参阅http://en.wikipedia.org/wiki/Sequence_point;您还可以更广泛地搜索“序列点”(即您的代码违反的规则集)。

Yes, that expression is undefined behavior as well (in C and C++). See http://en.wikipedia.org/wiki/Sequence_point for some information on the rules; you can also search for "sequence point" more generally (that is the set of rules that your code violates).

酒几许 2024-10-28 19:01:28

(这假设是 C 或 C++。)

Carl 的答案总体来说是准确的。

具体来说,问题就是耶利米指出的:序列点

澄清一下,代码块 (--i == ++i) 是一个“发生的事情”。这是一次性评估的一大块代码。首先发生的事情没有明确的顺序。可以先评估左侧,也可以评估右侧,或者可以比较相等性,然后递增 i,然后递减。其中每种行为都可能导致该表达式产生不同的结果。这里会发生什么是“未定义的”。你不知道答案是什么。

将此与语句 i = i+1 进行比较;这里,总是先评估右侧,然后将其结果存储到 i 中。这是明确定义的。没有任何歧义。

希望有一点帮助。

(This assumes C or C++.)

Carl's answer is exact in general.

In specific, the problem is what Jeremiah pointed out: sequence points.

To clarify, the chunk of code (--i == ++i) is a single "happening". It's a chunk of code that's evaluated all at once. There is no defined order of what happens first. The left side could be evaluated first, or the right side could, or maybe the equality is compared, then i is incremented, then decremented. Each of these behaviors could cause this expression to have different results. It's "undefined" what will happen here. You don't know what the answer will be.

Compare this to the statement i = i+1; Here, the right side is always evaluated first, then its result is stored into i. This is well-defined. There's no ambiguity.

Hope that helps a little.

末蓝 2024-10-28 19:01:28

在 C 中结果未定义,在 C# 中结果已定义。

在 C 中,比较被解释为:

以任意顺序执行所有这些操作:
- 减少i,然后将i的值取入x
- 将i的值代入y,然后增加i
然后比较 x 和 y。

在C#中,有更多的操作边界,因此比较被解释为:

减少i
然后将i的值放入x
然后将 i 的值放入 y
然后增加i
然后比较 x 和 y。

由编译器选择在操作边界内执行操作的顺序,因此将矛盾的操作放在同一边界内会导致结果不确定。

In C the result is undefined, in C# it's defined.

In C, the comparison is interpreted as:

Do all of these, in any order:
- Decrease i, then get value of i into x
- Get value of i into y, then increase i
Then compare x and y.

In C# there are more operation boundaries, so the comparison is interpreted as:

Decrease i
then get value of i into x
then get value of i into y
then increase i
then compare x and y.

It's up to the compiler to choose in which order the operations are done within an operation boundary, so putting contradictory operations within the same boundary causes the result to be undefined.

原野 2024-10-28 19:01:28

因为 C 标准是这么规定的。您的示例清楚地显示了未定义的行为。

根据评估顺序,比较应为 4 == 55 == 6。但条件返回 True。

Because the C standard states so. And your example clearly shows an undefined behabiour.

Depending on the order of evaluation, the comparison should be 4 == 5 or 5 == 6. And yet the condition returns True.

混吃等死 2024-10-28 19:01:28

您之前的问题被标记为 [C],因此我将基于 C 进行回答,即使您当前问题中的代码看起来不像 C。C99

中未定义行为的定义如下(第 3.4.3 节):
1 个未定义的行为
使用不可移植或错误的程序构造或错误数据时的行为,
2 注:可能的未定义行为包括完全忽略具有不可预测结果的情况,到在翻译或

程序执行期间以环境特有的记录方式表现(无论是否发出诊断消息),终止翻译或执行(通过发出诊断消息)。

C 标准的附录 J.2 有一个(很长——几页)未定义行为的列表,但即使这样仍然不够详尽。在大多数情况下,未定义的行为意味着您违反了规则,因此了解它的方法就是了解规则。

Your previous question was tagged [C], so I'm answering based on C, even though the code in your current question doesn't look like C.

The definition of undefined behavior in C99 says (§3.4.3):
1 undefined behavior
behavior, upon use of a nonportable or erroneous program construct or of erroneous data,
for which this International Standard imposes no requirements

2 NOTE Possible undefined behavior ranges from ignoring the situation completely with unpredictable results, to behaving during translation or program execution in a documented manner characteristic of the environment (with or without the issuance of a diagnostic message), to terminating a translation or execution (with the issuance of a diagnostic message).

Appendix J.2 of the C standard has a (long -- several pages) list of undefined behavior, though even that still isn't exhaustive. For the most part, undefined behavior means you broke the rules, so the way to know it is to know the rules.

最笨的告白 2024-10-28 19:01:28

未定义的行为==无论何时在完全相同的条件下运行它,都不能保证结果始终相同,或者无论何时使用不同的编译器或运行时执行它,都不能保证结果始终相同。

在您的代码中,由于它使用等于比较运算符,因此未指定应首先执行操作数的哪一侧,因此 --ii++ 可能会首先运行,您的答案将取决于编译器的实际实现。如果先执行--i,则为4 == 4,i=5;如果先实现i++,则为5 == 5,i=5。

答案可能相同的事实并不能阻止编译器警告您这是一个未定义的操作。

现在,如果这是一种定义左侧(或右侧)应始终首先执行的语言,那么行为将不再是未定义的。

Undefined behavior == the result cannot be guaranteed to always be the same whenever you run it in the exact same conditions, or the result cannot be guaranteed to always be the same whenever you use different compilers or runtimes to execute it.

In your code, since it is using a equal comparison operator which does not specify which side of the operands should be executed first, --i or i++ may end up running first, and your answer will depend on the actual implementation of the compiler. If --i is executed first, it will be 4 == 4, i=5; if i++ is implemented first, it will be 5 == 5, i=5.

The fact that the answer may turn out to be the same does not prevent the compiler from warning you that this is an undefined operation.

Now if this is a language that defines that the left hand side (or right hand side) should always be executed first, then the behavior will no longer be undefined.

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