Диагностическое правило основано на руководстве MISRA (Motor Industry Software Reliability Association) по разработке программного обеспечения.
Правило актуально только для языка C.
Согласно пункту 7.20.4 стандарта C11 аргументы макросов для целочисленных констант должны соответствовать следующим требованиям:
INT8_C должно находится в диапазоне [-128 .. 127].Отметим отдельно, что аргумент должен быть именно целочисленным литералом. Это исключает любые другие выражения, в том числе с унарным минусом.
Кроме того, неправильное использование макросов для целочисленных констант может приводить к неожиданному поведению.
Рассмотрим пример:
void do_something_ui(unsigned int value);
void do_something_ul(unsigned long value);
void do_something(unsigned long long);
#define DO_SOMETHING(X) Generic( (X) \
, unsigned int: do_something_ui \
, unsigned long: do_something_ul \
, default: do_something ) (X)
int foo(void)
{
DO_SOMETHING(UINT32_C(16L));
}
При компиляции этого кода препроцессор преобразует макровызов UINT32_C(16L) в числовой литерал 16LU, имеющий тип unsigned long. В результате выражение generic selection выберет ассоциацию unsigned long, и произойдёт вызов функции do_something_ul. Такое поведение может быть неожиданным для разработчика, который рассчитывал на то, что результатом вызова макроса будет литерал типа unsigned int и предполагалось, что произойдёт вызов функции do_something_ui.
Исправленный пример:
void do_something_ui(unsigned int value);
void do_something_ul(unsigned long value);
void do_something(unsigned long long);
#define DO_SOMETHING(X) Generic( (X) \
, unsigned int: do_something_ui \
, unsigned long: do_something_ul \
, default: do_something ) (X)
int foo(void)
{
DO_SOMETHING(UINT32_C(16));
}
Данная диагностика классифицируется как:
|