# V2652. MISRA. Argument of an integer constant macro should have an appropriate form.

Диагностическое правило основано на руководстве 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));
    }

Данная диагностика классифицируется как:

MISRA-C-2023-7.5