快捷方式记住C语言运算符的求值顺序和优先级

21 浏览
0 Comments

快捷方式记住C语言运算符的求值顺序和优先级

这个问题已经有答案了:

为什么这些使用前缀和后缀递增的构造是未定义的行为?

有没有快捷的方法或最佳途径来记住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++应该首先被评估,请告诉我是否错误,并请解释它的运作方式..

admin 更改状态以发布 2023年5月21日
0
0 Comments

记忆C运算符优先级的一种快捷方法。

PUMA IS REBL(拼“REBL”就像“REBEL”一样)。

“IS”中的“I”不代表任何运算符,只是为了完成句子。

(注意: 所有没有指定结合性的运算符都是从左到右的)。

P - Primary(主要)

U - Unary(一元)

M - Multiplicative(乘法)

A - Additive(加法)

S- Shift(移位)

R- Relational(比较)

E- Equality(等于)

B- BitWise(位运算& gt; ^ & gt; | )

L- Logical(逻辑运算logical && & gt; logical ||)

最后三个运算符分别是:

T- Ternary(三元)

A- Assignment(赋值)

C- Comma(逗号)

(像TACO一样,T代表三元,A代表赋值,Co代表逗号。)

对于结合性,除了一元、赋值和三元以外,其他运算符都是从左到右的(AUTO是从右边走的,即赋值、一元和三元是从右到左的)。

建议查看注释以获得更多信息。

0
0 Comments

首先,形如a++ + ++a++a + a++等表达式会导致未定义行为,任何结果都是可能的。从语言标准(n1256)可知:

6.5 表达式
……
2 在相邻的两个序列点前后,一个对象通过对表达式的求值最多被修改一次。72)此外,只能读取先前的值以确定要存储的值。73)
……
72) 浮点状态标志(flag)不是对象,可以在表达式中设置多次。

73) 该段落使得i = ++i + 1;a[i++] = i;等语句出现未定义的状态,但允许i = i + 1;a[i] = i;等语句

因此,请勿这样做。
x = a++ + ++b这样定义良好的表达式将被解析为x = ((a++) + (++b))。两种形式的++运算符的优先级高于加法,而加法的优先级高于赋值。该表达式的结果将与x = a + (b + 1)相同。

其次,请记住++--运算符都具有结果和副作用,如下所示:

  表达式                结果              副作用
  ----------          ------         -----------
       i++               i            i = i + 1
       ++i           i + 1            i = i + 1
       i--               i            i = i - 1
       --i           i - 1            i = i - 1

需要记住的重要一点是:副作用不必在表达式被求值后立即应用,它只需要在下一个序列点之前应用。因此,x = a++ + ++b可能以如下方式进行评估:

t1 = a;
t2 = b + 1;
x = t1 + t2;
b = b + 1;
a = a + 1;  


在这种情况下,对ab的更新被延迟到加法和赋值给x之后。

关于优先级,以下是从高到低的一般顺序:

  1. 后缀运算符(所有后缀运算符的优先级相同,因此运算符序列将从左到右求值)
    • 数组下标运算符[]
    • 函数调用运算符()
    • 成分选择运算符.->
    • 后缀++和--
  2. 一元运算符(所有一元运算符的优先级相同,因此序列将从左到右求值)
    • 前缀++和--
    • sizeof
    • 按位取反运算符~
    • 逻辑非运算符!
    • 一元符号操作符-+
    • 取地址运算符&
    • 解引用运算符*
  3. 强制类型转换表达式(类型名)
  4. 乘法运算符*/%
  5. 加法运算符+-
  6. 移位运算符<<>>
  7. 关系运算符<><=>=
  8. 相等运算符==!=
  9. 按位与&
  10. 按位异或^
  11. 按位或|
  12. 逻辑与&&
  13. 逻辑或||
  14. 条件运算符?:
  15. 赋值运算符=, +=,-=, *=, /=, %=, <<=,>>=, &=, ^=, |=
  16. 顺序(逗号)运算符,

因此,像*x++这样的表达式将被解析为*(x++),因为后缀++的优先级高于一元*。同样,sizeof x + 1将被解析为(sizeof x) + 1,因为sizeof的优先级高于加法。表达式p++->x将被解析为(p++)->x,因为后缀++->运算符的优先级相同,因此它们将从左到右解析。

这是最短的快捷方式之一; 当有疑问时,请使用括号。

0