主要内容

本页采用了机器翻译。点击此处可查看最新英文版本。

MISRA C:2012 Rule 12.1

The precedence of operators within expressions should be made explicit

描述

规则定义

The precedence of operators within expressions should be made explicit 1 .

理由

C 语言有大量的运算符,它们的优先级并不直观。缺乏经验的程序员很容易犯错。使用括号显式定义运算符优先级,以消除歧义。

下表列出了本规则中运算符优先级的 MISRA C™ 定义。

描述操作符和操作数优先级
主要标识符、常量、字符串字面量、(表达式)16
后缀[] ()(函数调用). -> ++(后置自增)--(后置自减)() {}(C99:复合字面量)15
一元

++(前置自增)--(前置自减)& * + - ~ ! sizeof _Alignof defined(预处理器)

14
强制类型转换()13
乘法* / %12
加法+ -11
按位移位<< >>10
关系<> <= >=9
相等== !=8
位与&7
位异或^6
位或|5
逻辑与&&4
逻辑或||3
条件?:2
赋值= *= /= += -= <<= >>= &= ^= |=1
逗号,0

表达式的优先级是表达式解析树的“根”元素的优先级。换句话说,一个表达式的优先级就是该表达式中最后执行的运算的优先级。例如,考虑以下表达式:

a - b << c + d
该表达式的根运算符为 <<,其优先级为 10。操作数 a - bc + d 的秩为 11。

根据表达式及其子表达式的优先级,MISRA C:2012 标准建议:

  • sizeof 运算符的操作数用括号括起来。

  • 如果满足以下所有条件,请用括号括住表达式的操作数:

    • 操作数的优先级小于 13。

    • 操作数比表达式具有更高的优先级。

    • 该表达式本身的优先级在 2 到 12 之间。

Polyspace 实现

如果满足以下任何条件,规则检查器都会报告违规:

  • 表达式中的操作数比表达式的根运算符具有更高的优先级,但操作数未用括号括起。

  • sizeof 运算符的操作数不使用括号。

赋值运算符、单项运算符、下标运算符和逗号运算符不会报告违反此规则的情况。

故障排除

如果您预期会出现违规,但未看到该违规,请参阅诊断为何编码规范违规未按预期显示

示例

全部展开

int a, b, c, d, x;

void foo(void) {
  x = sizeof a + b;                     /* Non-compliant - MISRA-12.1 */ 
  
  x = a == b ? a : a - b;               /* Non-compliant - MISRA-12.1 */ 

  x = a <<  b + c ;                     /* Non-compliant - MISRA-12.1 */ 

  if (a || b && c) { }                  /* Non-compliant - MISRA-12.1 */ 

  if ( (a>x) && (b>x) || (c>x) )   { }  /* Non-compliant - MISRA-12.1 */ 
}

此示例显示了各种违反 MISRA™ 规则 12.1 的情况。在每次违规运算中,如果不清楚运算顺序,代码可能会执行出意料的结果。

更正 - 用括号进行说明

为了遵守此 MISRA 规则,请在表达式中的各个运算符周围添加括号。这里展示了一种可能的解决方案。

int a, b, c, d, x;

void foo(void) {
  x = sizeof(a) + b;
  
  x = ( a == b ) ? a : ( a - b );

  x = a << ( b + c );

  if ( ( a || b ) && c) { }

  if ( ((a>x) && (b>x)) || (c>x) ) { }
}
# if defined X && X + Y > Z    /* Non-compliant - MISRA-12.1 */ 
# endif

在此示例中,预处理代码中显示了违反 MISRA 规则 12.1 的情况。在这种情况下,如果您不知道正确的运算顺序,结果可能会出人意料并引发问题。

更正 - 用括号进行说明

为了遵守此 MISRA 规则,请在表达式中的各个运算符周围添加括号。这里展示了一种可能的解决方案。

# if defined (X) && ( (X + Y) > Z )
# endif
int a, b, c, x,i = 0;
struct {int a; } s, *ps, *pp[2];

void foo(void) {
	ps = &s;
	pp[i]-> a;          /* Compliant - no need to write (pp[i])->a */
	*ps++;              /* Compliant - no need to write *( p++ ) */ 

	x = f ( a + b, c ); /* Compliant - no need to write f ( (a+b),c) */

	x = a, b;           /* Compliant - parsed as ( x = a ), b */

	if (a && b && c ){  /* Compliant - all operators have
					* the same precedence */
	}
}

在此示例中,所示表达式具有多个运算。但是,这些表达式是合规的,因为运算符优先级已经很明确了。

检查信息

组:表达式
类别:建议
AGC 类别:建议

版本历史记录

全部展开


1 All MISRA coding rules and directives are © Copyright The MISRA Consortium Limited 2021.

The MISRA coding standards referenced in the Polyspace Bug Finder™ documentation are from the following MISRA standards:

  • MISRA C:2004

  • MISRA C:2012

  • MISRA C:2023

  • MISRA C++:2008

  • MISRA C++:2023

MISRA and MISRA C are registered trademarks of The MISRA Consortium Limited 2021.