C# (-i==i+;+;)是一种未定义的行为吗?

C# (-i==i+;+;)是一种未定义的行为吗?,c#,undefined-behavior,C#,Undefined Behavior,这个问题与我以前的问题有关。我得到的答案是“这是一种未定义的行为。” 请任何人解释: 什么是未定义的行为 我怎么知道我的代码有未定义的行为 示例代码: 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 什么是未定义

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

请任何人解释:

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

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
什么是未定义的行为

它只是任何没有被适当的语言规范明确定义的行为。有些规范会将某些内容列为明确未定义,但实际上,任何未定义的内容都是未定义的

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

希望您的编译器会警告您——如果不是这样,您需要阅读语言规范,了解所有导致这些问题的有趣的角落和角落


外面要小心

是的,该表达式也是未定义的行为(在C和C++中)。有关规则的一些信息,请参阅;您还可以更一般地搜索“序列点”(即您的代码违反的一组规则)。

因为C标准如此规定。您的示例清楚地显示了一个未定义的行为


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

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

根据C#(ECMA-334)规范“运算符优先级和关联性”章节(§14.2.1):

  • 除了赋值运算符和空合并运算符之外,所有 剩下的是二进制运算符- 关联的,意思是 从左到右执行。 [示例:x+y+z评估为(x+y)+z。结束示例]

因此,首先计算
--i
,将
i
更改为4,然后计算为4。然后,
i++
正在求值,将
i
更改为5,但求值为4。

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

C99中未定义行为的定义是(§3.4.3):
1未定义的行为
使用不可移植或错误的程序结构或错误的数据时的行为, 本国际标准对其无任何要求

2注:可能的未定义行为范围从完全忽略情况到不可预测的结果,到在翻译或程序执行过程中以环境特有的记录方式(无论是否发出诊断消息)表现,再到终止翻译或执行(发出诊断信息)


C标准的附录J.2有a(长——几页)未定义行为的列表,尽管还不是详尽无遗的。在大多数情况下,未定义行为意味着您违反了规则,因此了解它的方法就是了解规则。

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

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

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

现在,如果这是一种定义左手(或右手边)应该首先执行的语言,那么行为将不再是未定义的。< /P> < P>(假定C或C++)< /P> 卡尔的回答大体上是准确的

具体而言,问题是耶利米指出的:

为了澄清,代码块(--i==++i)是一个“正在发生的”。这是一段一次性计算的代码。没有定义先发生什么的顺序。可以先计算左侧,也可以先计算右侧,或者比较等式,然后递增,然后递减。每种行为都可能导致此表达式产生不同的结果。它是“未定义的”这里会发生什么,你不知道答案是什么

将其与语句i=i+1进行比较;这里,总是首先计算右侧,然后将其结果存储到i中。这是定义良好的。没有歧义


希望这有点帮助。

在C中,结果是未定义的,在C中,结果是已定义的

在C中,比较被解释为:

按任何顺序执行所有这些操作:
-减小
i
,然后将
i
的值放入x
-将
i
的值取为y,然后增加
i

然后比较x和y

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

减少
i

然后将
i
的值放入x
然后将
i
的值输入y
然后增加
i

然后比较x和y


编译器可以选择在操作边界内执行操作的顺序,因此在同一边界内放置相互矛盾的操作会导致结果未定义。

您使用的是哪种语言?C和C非常不同H、C或C?这不是有效的C,为什么要添加标记?“什么是未定义的行为?”其3或428,3取决于附近的重力和发电厂。你为什么要这样写,以迷惑你的程序员同伴?Console.WriteLine()在C中做什么?该语句来自哪里?C或C?定义正确,b