2009-12-28 151 views
0

我对评估的优先顺序和顺序感到困惑。请用一个例子来解释我优先次序和评估顺序

+2

你的问题是什么? – qrdl 2009-12-28 11:52:00

+0

我认为他正在努力处理运营商优先级 – 2009-12-28 11:55:26

回答

2

回想一下早期的小学数学。

什么是4 + 3 * 2?
是14还是10?

当然,它是10,因为加法运算符比乘法运算符的优先级低,所以4 + 3 * 2总是意味着4 +(3 * 2)。

操作顺序只是您根据其操作符来评估子表达式的顺序。

括号,指数,除法,乘法,加法,减法。很显然,在编程中(当然也有数学)还有更多的操作符,但我从来没有听说过基本基础数学以外的操作顺序。

只需等到您了解运营商中的左关联和右关联即可。

4

优先级指定如何在逻辑上评估表达式。例如,优先级说,在表达

X + Y * Z

表达式必须为x +(Y * Z)进行评估。

但是,C没有尝试说出必须首先评估什么。在上面的例子中,可以先评估x,然后(y * z)。或者,可以评估(y * z),然后是x。有一些例外 - 例如& &和||操作员指定特定的顺序,但总的来说,不依赖于顺序是明智的。

5

这是一个秘密:我不打扰学习优先规则。他们很容易出错,并且让下一个看代码的人觉得太多了。解释:假设维护你的代码的人是一位斧头精神病患者,他知道你住在哪里。他们也很好。

因此,而不是:

x = a + b * c/d; 

我会用:

x = a + ((b * c)/d); 

或许更好(主观),将它分解为单独的语句棘手的问题,或许是在发生什么。“巧妙“的代码行,对表达式后面的表达有副作用:

x = Func(z) * a[i++] + i; // where Func(z) somehow mutates i 
          // (or even worse when using "conditional" etc) 

应该谨慎使用这些东西,并且应该尝试了解哪些行为是定义的,哪些是明确未定义的,但取决于您使用的编译器是否工作(或失败)。

+0

+1的概念以获得正确的建议。 对于CS课程学习这个概念很重要,但更好的是在现实生活场景中添加括号。 – Jack 2009-12-28 12:27:48

0

是关当然,我打了这个运营商(& & ||)仅.. ++运算符具有比逻辑与更高的优先级(& &)和逻辑OR(||)。所以在表达式中

m = ++ i & & ++ j || ++ k;

我以为是变量i,j和k将递增,然后逻辑运算将实际被evaluated..But它不是happened.variable k不是递增..

逻辑OR的左值已经TRUE所以它从来没有考虑过它的R值执行... 因此变量k不会递增。但是++运算符的优先级发生了什么......为什么逻辑运算符首先计算,比增量运算符优先级低。

+0

&&和||运营商是不寻常的,因为他们指定了评估顺序 - 他们总是从左到右进行评估。优先级对评估顺序没有影响。 – 2009-12-28 12:22:56

+0

即使这与问题无关,请注意您的术语:++ i && ++ j不是左值。左值是可以分配给的值(可以显示在赋值运算符的左侧),而不是任何运算符左侧出现的值。 – Gorpik 2009-12-28 12:37:00

+0

||和&&是'序列点'。这意味着所有的副作用都必须先解决任何副作用。 “短路评估”是另一个话题。 – 2010-07-28 10:06:29

0

这里有一个简单的方法来记住这一切:

加号和减号是非常强大的C,尽管他们在数学的东西。它们几乎和*和/(当然,它们更强大,就像数学一样)强大。

逻辑& &和||比比较弱,这样你就可以问,如果(> 5 & & b < 6)没有括号。但是,按位& | (由于某种原因),因此如果((b)> 5)需要大括号。这是唯一不合逻辑的地方。由于布尔代数语义(AND被认为是乘法),AND总是比OR更强。

比较和+之间 - 我们有位移位。它们属于近似的算术运算,而不是按位运算。所以,cout < < a & b已损坏。

其余部分是显而易见的。全表是here

0

从C语言程序设计下表,由Kernighan和Ritchie,示出了优先级的层次结构中C.上方的行的优先级最高。

Operators         Associativity 
([ - .         Left to right 
! - ++ -{- + * & (type-cast) sizeof Right to left 
(in the above line, +, - and * are the unary forms) 
*/%          Left to right 
+ -          Left to right 
<< >>          Left to right 
< <= > >=        Left to right 
== !=          Left to right 
&           Left to right 
^           Left to right 
|           Left to right 
&&           Left to right 
||           Left to right 
?:           Left to right 
= += -= *= /= %= &= ^= |= <<= >>= Right to left 
,           Left to right 

实施例: http://www.careercampus.net/resources/data_and_c_next1.htm

4

优先定义了运营商的应用顺序:例如,在表达式a * b + c/d - e中,“*”和“/”运算符具有比更高的优先级的' +'和' - '运算符,因此表达式评估为(a * b) + (c/d) - e;即将a * b的结果添加到c/d的结果中,并从该总和中扣除e

评估顺序指的是评估子表达的顺序。由a * b + c/d - e前面的例子中去,编译器可以决定评估a * b之前评估c/d; IOW在大多数情况下不能保证评估从左到右进行。如果我们改变的变量函数,即a() * b() + c()/d() - e(),有没有保证a()b()之前调用,或b()c()之前调用等编译器可以决定调用e(),再c(),然后d()。等所有的保证是a() * b()的结果将被添加到c()/d()的结果中,并且e()将从该总和中被减去,而不管a(),b(),c(),d(),和e()被调用。某些运营商(如逗号运算符)和逻辑运算符&&||强制执行部分评估顺序;给定表达式a() == b() && c() == d(),&&操作员力a() == b()c() == d()之前被评估,但它不强制a()b()之前被呼叫。

1

比方说,你有三个功能:

int a(void) { return printf("Hi!\n"); } 
int b(void) { return printf("I am in b\n"); } 
int c(void) { return printf("c\n") } 

然后将下面的函数调用:

printf("The answer to life, universe and everything is: %d.\n", 
    a() * b() + c()); 

将打印在指定顺序串Hi!I am in bc(每一个换行符),然后是The answer to life, universe and everything is: 42.,然后是换行符。

优先告诉我们,*+更高的优先级,所以a() * b() + c()将被解释为(a() * b()) + c(),而不是a() * (b() + c())。另一方面,评估顺序将暗示调用的顺序为a(),b()c()。在这里,他们可以按任何顺序进行评估。例如,编译器可以先调用c(),然后调用b(),然后调用a(),存储中间值,然后根据优先级规则计算表达式。

当然,编译器必须评估a()b()都来计算的总和,但它可以评估c()后也这样做,并能a()之前评估b()