Main Content

MISRA C:2023 Rule 12.1

The precedence of operators within expressions should be made explicit

Since R2024a

Description

Rule Definition

The precedence of operators within expressions should be made explicit.

Rationale

The C language has a large number of operators and their precedence is not intuitive. Inexperienced programmers can easily make mistakes. Remove any ambiguity by using parentheses to explicitly define operator precedence.

The following table list the MISRA C™ definition of operator precedence for this rule.

DescriptionOperator and OperandPrecedence
Primaryidentifier, constant, string literal, (expression)16
Postfix[] () (function call) . -> ++(post-increment) --(post-decrement) () {}(C99: compound literals)15
Unary

++(pre-increment) --(pre-decrement) & * + - ~ !sizeof_Alignofdefined (preprocessor)

14
Cast()13
Multiplicative* / %12
Additive+ -11
Bitwise shift<< >>10
Relational<> <= >=9
Equality== !=8
Bitwise AND&7
Bitwise XOR^6
Bitwise OR|5
Logical AND&&4
Logical OR||3
Conditional?:2
Assignment= *= /= += -= <<= >>= &= ^= |=1
Comma,0

The precedence of an expression is the precedence of the 'root' element of the parse tree of the expression. In other words, the precedence of an expression is the precedence of the operation that is performed last in the expression. For example, consider this expression:

a - b << c + d
The root operator of this expression is <<, which has a precedence of 10. The operands a - b and c + d have a rank 11.

Using the precedence of an expression and its subexpression, the MISRA C:2023 standard recommends:

  • Enclose the operands of sizeof operator in parenthesis.

  • Enclose an operand of an expression in parenthesis if all these conditions are true:

    • The operand has a precedence less than 13.

    • The operand has a greater precedence than the expression.

    • The precedence of the expression itself if between 2 to 12.

Polyspace Implementation

The rule checker reports a violation if any of these conditions are true:

  • The operands of an expression has a higher precedence than the root operator of the expression but the operands are not parenthesized.

  • The operands of sizeof operator do not use parenthesis.

Violations of this rule is not reported for assignment operators, unary operators, subscripting operators, and comma operators.

Troubleshooting

If you expect a rule violation but do not see it, refer to Diagnose Why Coding Standard Violations Do Not Appear as Expected.

Examples

expand all

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 */ 
}

This example shows various violations of MISRA™ rule 12.1. In each violation, if you do not know the order of operations, the code could execute unexpectedly.

Correction — Clarify With Parentheses

To comply with this MISRA rule, add parentheses around individual operations in the expressions. One possible solution is shown here.

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

In this example, a violation of MISRA rule 12.1 is shown in preprocessing code. In this violation, if you do not know the correct order of operations, the results can be unexpected and cause problems.

Correction — Clarify with Parentheses

To comply with this MISRA rule, add parentheses around individual operations in the expressions. One possible solution is shown here.

# 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 */
	}
}

In this example, the expressions shown have multiple operations. However, these expressions are compliant because operator precedence is already clear.

Check Information

Group: Expressions
Category: Advisory
AGC Category: Advisory

Version History

Introduced in R2024a

expand all