Main Content

MISRA C:2023 Rule 10.8

The value of a composite expression shall not be cast to a different essential type category or a wider essential type

Since R2024a

Description

Rule Definition

The value of a composite expression shall not be cast to a different essential type category or a wider essential type.

Rationale

A composite expression is a non-constant expression using a composite operator. In the Essential Type Model, composite operators are:

  • Multiplicative (*, /, %)

  • Additive (binary +, binary -)

  • Bitwise (&, |, ^)

  • Shift (<<, >>)

  • Conditional (?, :)

Unary operators such as ~ and unary + or - are also considered composite operators.

Casting to a wider type is not permitted because the result may vary between implementations. Consider this expression:

(uint32_t) (u16a +u16b);
On a 16-bit machine the addition is performed in 16 bits. The result is wrapped before it is cast to 32 bits. On a 32-bit machine, the addition takes place in 32 bits and preserves high-order bits that are lost on a 16-bit machine. Casting to a narrower type with the same essential type category is acceptable as the explicit truncation of the results always leads to the same loss of information.

For more information on essential types, see MISRA C:2012 Rule 10.1.

Polyspace Implementation

The rule checker reports a violation only if the result of a composite expression is directly cast to a different or wider essential type. Unary operators are not considered as composite operators.

For instance, in this example, a violation is shown in the first assignment to i but not the second. In the first assignment, a composite expression i+1 is directly cast from a signed to an unsigned type. In the second assignment, the composite expression is first cast to the same type and then the result is cast to a different type. Since the composite expression is not directly cast to a different type, the checker does not raise a violation.

typedef int int32_T;
typedef unsigned char uint8_T; 
...
...
int32_T i;
i = (uint8_T)(i+1); /* Noncompliant */
i = (uint8_T)((int32_T)(i+1)); /* Compliant */

Polyspace® does not report a violation of this rule for these cases:

  • An essentially real floating expression is cast to an essentially complex floating type but the corresponding real type of the complex type is not wider than the type of the real expression.

  • An essentially real complex expression is cast to an essentially real floating type but the floating type is not wider than the corresponding real type of the complex expression.

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

In this example, rule 10.8 is violated in the following cases:

#include <stdint.h>
#include <complex.h>
extern unsigned short ru16a, u16a, u16b;
extern unsigned int   u32a, ru32a;
extern signed int     s32a, s32b;

void foo(void)
{
  ru16a  = (unsigned short) (u32a + u32a);/* Compliant                           */
  ru16a += (unsigned short) s32a;    /* Compliant - s32a is not composite        */
  ru32a  = (unsigned int) (u16a + u16b);  /* Noncompliant - wider essential type */
}

void bar(int8_t i8x, int8_t i8y, float fx, float fy){
	
	(_Complex float) (i8x + i8y);      /* Noncompliant - wider essential type */ 
	 (_Complex float) (fx + fy);       /* Compliant                           */    
}

  • s32a and s32b are essentially signed variables. However, the result ( s32a + s32b ) is cast to an essentially unsigned type.

  • u16a and u16b are essentially unsigned short variables. However, the result ( s32a + s32b ) is cast to a wider essential type, unsigned int.

  • i8x and i8y are essentially 8-bit signed integers, but are converted to a wider essential type _complex float.

Check Information

Group: The Essential Type Model
Category: Required
AGC Category: Advisory

Version History

Introduced in R2024a