记住C中运算符的评估顺序和优先级的快捷方式[重复]
Posted
技术标签:
【中文标题】记住C中运算符的评估顺序和优先级的快捷方式[重复]【英文标题】:Shortcut to remember the Order of Evaluation and Precedence of Operators in C [duplicate] 【发布时间】:2011-05-11 10:29:30 【问题描述】:是否有任何捷径或最佳方式来记住 C 中评估的优先级和顺序,因为它起着主要作用,而我或(我们大多数人)通常会忘记并最终陷入混乱。请帮帮我....
我想举个例子……说……
void main()
int a=1;
a = a++ + ++a;
printf("%d",a);
//prints 5;
void main()
int a=1;
int x;
x = a++ + ++a;
printf("%d",x);
//prints 4;
还有表达式x = ++a + a++;
给出不同的结果
我希望如果帖子增量具有高优先级,则应首先评估 a++
如果我错了请清除我,并请解释我是如何工作的..
【问题讨论】:
怎么样:“总是使用括号”? 我不喜欢无偿使用括号(括号)。了解您的运营商。 @DrAl 听起来像个计划!! 【参考方案1】:喜欢优点:不确定时添加括号。那你就不用记住了,加上代码会更容易阅读。
【讨论】:
【参考方案2】:如果您觉得它令人困惑,那么阅读您的代码的任何人都会如此。如有疑问,请使用括号强调。
【讨论】:
【参考方案3】:我同意其他帖子,始终尝试使用括号。但是,如果您不想这样做,您可以将其打印出来并贴在您的计算机或其他东西旁边。
C Operator Precedence Table【讨论】:
@Downvoter - 想发表评论吗?【参考方案4】:当涉及到运算符优先级时,你不应依赖你的记忆。只有在明显的情况下。其中是 - 算术运算符的存在,+ - * / %。还要知道 ++ 和 -- 具有比 * 更高的优先级才能正确读取 *p++ = *q++;
之类的表达式
按位运算有疯狂的优先规则。 总是对这些使用括号。
【讨论】:
+1 位运算符似乎与它们的布尔类似物具有相同的优先级,这就是为什么像a & mask == 1
这样的东西在过去一直困扰着我。【参考方案5】:
首先,a++ + ++a
、++a + a++
等形式的表达式会导致未定义的行为; 任何结果都是可能的。来自语言标准(n1256):
6.5 表达式 ... 2 在上一个序列点和下一个序列点之间,一个对象应该有它的存储值 通过表达式的评估最多修改一次。72) 此外,先验值 应为只读以确定要存储的值。73) ... 72) 浮点状态标志不是对象,可以在表达式中多次设置。 73) 本段呈现未定义的语句表达式,例如我=++我+1; a[i++] = i;同时允许 我 = 我 + 1; a[i] = i;
所以,不要那样做。
像x = a++ + ++b
这样定义明确的表达式将被解析为x = ((a++) + (++b))
; ++
运算符的两种形式的优先级都高于加法,加法的优先级高于赋值。表达式的result 将与x = a + (b + 1)
相同。
其次,记住++
和--
运算符有一个结果和一个副作用,如下图:
要记住的重要提示:不必在计算表达式后立即应用副作用;它只需要在下一个序列点之前应用。 x = a++ + ++b
的评估方式如下:
t1 = a;
t2 = b + 1;
x = t1 + t2;
b = b + 1;
a = a + 1;
在这种情况下,a
和 b
的更新将推迟到添加并分配给 x
之后。
就优先级而言,这是从高到低的一般顺序:
-
后缀运算符(都具有相同的优先级,因此运算符序列将从左到右计算)
数组下标运算符
[]
函数调用运算符()
组件选择运算符.
和->
后缀++
和--
一元运算符(都具有相同的优先级,因此运算符序列将从左到右计算)
前缀++
和--
sizeof
按位否定运算符~
逻辑否定运算符!
一元符号运算符-
和+
操作员地址&
取消引用运算符*
转换表达式(
类型名称 )
乘法运算符*
、/
、%
加法运算符+
和-
移位运算符<<
和>>
关系运算符<
、>
、<=
、>=
等式运算符==
和!=
按位与&
按位异或^
按位或|
逻辑与&&
逻辑或||
条件运算符?:
赋值运算符=
、+=
。 -=
, *=
, /=
, %=
, <<=
, >>=
, &=
, ^=
, |=
顺序(逗号)运算符,
因此,像*x++
这样的表达式被解析为*(x++)
,因为后缀++
的优先级高于一元*
。同样,sizeof x + 1
被解析为(sizeof x) + 1
,因为sizeof
的优先级高于加法。像p++->x
这样的表达式被解析为(p++)->x
;后缀++
和->
运算符具有相同的优先级,因此它们是从左到右解析的。
这与快捷方式一样短;如有疑问,请使用括号。
【讨论】:
非常感谢....太好了...我如何为这个答案添加声誉? 谢谢,我没有找到提到铸造运算符的参考资料。 @John Bode,您能解释一下如何评估 ++a + ++a 吗? @Venkatesh:见我回答的第一部分;评估是未定义。表达式将被解析为(++a) + (++a)
;但是,不能保证左侧表达式将在右侧表达式之前计算,也不能保证 ++
运算符的副作用在评估后立即应用。根据编译器、编译器设置,甚至是周围的代码,你会得到不同的结果。 ++a + ++a
是一个编码错误,句号。
@Venkatesh C 语言对处理词法标记很贪心,这意味着 ++a+++a 等价于 (++(a ++)) + a,但它是语法错误!错误:需要左值作为增量操作数 fprintf(stdout, "%u\n", ((++a)++)+a);【参考方案6】:
在 C 中,优先表指定表达式的计算顺序,也指定关联规则。使用该规则,我们可以计算表达式中的等优先级运算符(R->L OR L->R)。 您指定, a = 1; x = a++ + ++a; 1: ++a 然后 exp: a(2)++ + 2 = 4 分配给 x 2:然后增加 a ,变成 a = 3
假设,a = a++ + ++a;然后 增加一个 2 + 2 分配给 a(4)。 增加 a(5)。
【讨论】:
您好,谢谢...但是后增量的优先级最高,然后在表达式 x=a++ + ++a;.... a++ 应该首先执行对吧?即 x= 1 + 3 是这样的吗?那么 exp a=a++ + ++a 应该也是一样的吧? x = ++a;和 x = a++;对 x 给出不同的答案。这里 ++a 做第一个并添加 a + a 的当前值,然后分配给 x。再次增加 a 的值后 你能不能用一般的方式解释一下控制流以便它适用于像这样的任何类型的exp???? 请参考 Dennis Ritchie 的 C 编程... Precedence 未指定评估顺序。a++ + ++a
的行为是undefined。 (并且添加括号不会改变这一点。)【参考方案7】:
Promod 的回答或他的解释不正确
要记住的正确方法是
在所有前置操作符中 -pre 增量具有最高优先级
在所有的后增量操作中,后增量的优先级最低
加法的优先级低于前后自增运算符
现在考虑 Pre increment 属于从右到左的范畴
而Post增量属于从左到右的类
综合这两种情况可以算出代码
i = 1;
i=i++ + ++i + ++i + i++;
不是14岁而是12岁
中间两个表达式计算为 4 然后是 4+4+4
"后缀递增/递减优先级高,但实际 操作数的递增或递减被延迟(待完成 在语句完成执行之前的某个时间)。 "
这是证明链接 enter link description here
【讨论】:
该表达式具有未定义的行为。 John Bode 的回答解释了原因。看到特定实现的结果并不能证明任何事情。 @Keith Thompsan 但是对于少数简单的情况,您不会说 m++ 是未定义的,您不能仅凭看到 ++ 就排除任何未定义的情况。创造语言的人比你好。他们更好地了解 undefined 的含义,他们定义 ++ 是有原因的。当与许多其他运算符连接时,它的结果是未定义的,但只是看到 ++ 并将表达式判定为未定义是无知的 当然++
本身并不是未定义的。从来没有人说它是。如果您知道答案中表达式的行为是未定义的,您为什么要试图证明它导致 12 而不是 14?你到底是什么意思?
我的意思是答案 14 是错误的,如果没有实施,答案将是 14 。这家伙甚至确实编写了代码并使用了一些“辅导班技巧”来找出 14
您需要了解“未定义行为”的含义。结果没有理由不能是 14、12、42、分段错误或泛黄。而且您关于运算符优先级的说法也不正确;所有后缀运算符具有相同的优先级,所有(前缀)一元运算符具有相同的优先级。【参考方案8】:
要了解运算符优先级,请尝试以下操作: 1:ARLA 表示: A->算术运算符 R->关系运算符 L->逻辑运算符 A-> 赋值运算符 2:博德马斯 B=括号优先( (,) ) O=订单(如幂和平方等,) D=除法(/) M=乘法(*) A=加法(+) S=减法(-)
【讨论】:
【参考方案9】:有一个快捷方式可以记住 C 运算符的优先级。
PUMA IS REBL(将“REBL”拼成“REBEL”)。
IS中的“I”不代表任何运算符,用于句子的完成。
(注意:所有未指定结合性的运算符都是从左到右的)。
P - 主要
U - 一元
M - 乘法
A - 添加剂
S-Shift
R- 关系
E-平等
B- BitWise ( & > ^ > |)
L- 逻辑(逻辑 && > 逻辑 ||)
最后三个运算符是
T- 三元
A- 作业
C- 逗号
(TACO 如 (https://en.wikipedia.org/wiki/Taco) T 表示三进制,A 表示赋值,Co 表示逗号)。
对于关联性除了一元、赋值和三元之外的所有都是 从左到右(AUTO 骑在右边,即赋值、一元和三元从右到左)。
建议查看 cmets 了解更多信息。
【讨论】:
所以,更像是 PUMA 的 REBL TAC(puma 是一只猫,因为我们的猫是拼写反叛者,所以它会倒写“cat”)。我会喜欢它,如果有一个快捷方式来记住“逻辑 && > 逻辑 ||”部分。 @Kaiserludi 这是一个有趣的故事,TAC 因为不合适所以被省略了,但是如果 PUMA 确实是 CAT,那么在最后反转它不是问题(尤其是因为它是拼写根据你的反叛:-))。最初我认为 PUMA 是一个鞋履品牌。可能是为了让我们可以思考一些有趣的事情。 @Kaiserludi 所以故事就像“C”是一只 CAT,她是一个 REBEL,她的名字是 PUMA,她喜欢玩 SAND(如“地址”中使用的“和”和 '&' 和 '&&' ),喜欢看明星( * ,** 等)。 嗯,其实是一个拼写rebl,所以rebl也拼错了,因为那太叛逆了。而且,是的,美洲狮确实是一只猫。这是美洲狮或美洲狮的另一种说法。 如果您需要关联性的快捷方式,则“自动在右侧骑行”,表示赋值、一元和三元运算符从右到左,添加 O 以完成)【参考方案10】:计算简单 当你写 诠释一个= 1; x= a++ + ++a; 由于前缀增量运算符 (在 ++a 中)'a' 的值将等于 2 因此,当前表达式等价于 x=2+2; // x=4 由于后缀运算符,一旦控制进入下一行,a 的值就会增加 1,现在 a =3
现在检查这个语句 诠释一个= 1; a= a++ + ++a; 在此语句中,如上所述,“a”的值将等于表达式 a=2+2;。 // 表示 a=4 但是由于后缀增量运算符 (a++) 一旦控制转移到程序中的下一行,a 的值就会增加 1。所以 printf (%d,a); 打印 5 我希望这能消除你的疑问
【讨论】:
以上是关于记住C中运算符的评估顺序和优先级的快捷方式[重复]的主要内容,如果未能解决你的问题,请参考以下文章