V2653. MISRA. The small integer variants of the minimum-width integer constant macros should not be used.
Диагностическое правило основано на руководстве MISRA (Motor Industry Software Reliability Association) по разработке программного обеспечения.
Правило актуально только для языка C.
Стандарт C требует, чтобы макросы целочисленных констант минимальной ширины (пункт 7. 20. 1.2 стандарта C11) раскрывались в integer constant expression. Это выражение (пункт 7.20.4.3 стандарта C11) должно подходить для использования с директивами #if, а также его тип должен быть таким же, как если бы к аргументу макроса был применён integer promotion.
Использование макросов целочисленных констант минимальной ширины не рекомендуется, так как приводит к путанице с подставляемыми типами.
Рассмотрим следующий пример:
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 — это макрос в языке C, предназначенный для обозначения беззнаковых 8-битных целочисленных констант. Он определяется в стандартных заголовочных файлах, таких как <stdint.h>, и используется для обеспечения переносимости кода между различными платформами и компиляторами.
Ожидается, что результат раскрытия макроса UINT8_C будет иметь тип uint8_t. Однако после применения integer promotion, так как ранг uint8_t меньше, чем int, результат будет таким же, как если бы аргумент был подставлен в код без изменений как целочисленная константа 8.
В результате _Generic selection выберет ассоциацию function_int(int value) вместо ожидаемой function_u8(uint8_t value).
Исправленный пример:
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));
}
Данная диагностика классифицируется как:
|