V2653. MISRA. The small integer variants of the minimum-width integer constant macros should not be used.
This diagnostic rule is based on the MISRA (Motor Industry Software Reliability Association) software development guidelines.
This diagnostic rule is relevant only for C.
According to C11 (Section 7.20.1.2), the minimum-width macros of integer constants should be expanded into an integer constant expression. According to C11 (Section 7.20.4.3), the expression should comply with #if
directives, and its type should be the same as if integer promotion had been applied to the macro argument.
Using minimum-width integer constant macros is not recommended, as it leads to confusion with substituted types.
The example:
void function_u8(uint8_t value){}
void function_int(int value) {}
#define MACRO_U8(Z) _Generic((Z) \
, uint8_t: function_u8 \
, default: function_int)(Z)
void foo(void)
{
MACRO_U8(UINT8_C(8)); // <=
}
UINT8_C
is a C macro defined in standard header files (e.g., <stdint.h>
) to denote unsigned 8-bit integer constants. It is used to provide cross-platform and cross-compiler portability.
The result of expanding the UINT8_C
macro is expected to be of uint8_t
type. However, after applying integer promotion, since the rank of uint8_t
is less than int
, the result will be the same as if the argument had been substituted into the code without changes, as the integer constant 8
.
As a result, _Generic selection chooses the function_int(int value)
association instead of the expected function_u8(uint8_t value)
.
The fixed code:
void function_u8(uint8_t value){}
void function_int(int value) {}
#define MACRO_U8(Z) _Generic((Z) \
, uint8_t: function_u8 \
, default: function_int)(Z)
void foo(void)
{
MACRO_U8((uint8_t)(8));
}