Мы используем куки, чтобы пользоваться сайтом было удобно.
Хорошо
to the top
>
>
>
V2646. MISRA. All arguments of any...
menu mobile close menu
Проверка проектов
Дополнительная информация
toggle menu Оглавление

V2646. MISRA. All arguments of any multi-argument type-generic macros from <tgmath.h> should have the same type.

22 Июл 2025

Диагностическое правило основано на руководстве MISRA (Motor Industry Software Reliability Association) по разработке программного обеспечения.

Это правило актуально только для языка C.

Все аргументы, передаваемые в макросы из заголовочного файла <tgmath.h>, должны иметь одинаковый тип. Целочисленные аргументы после преобразования (integer promotion) также должны быть одного типа.

Правило применимо к следующим макросам: atan2, copysign, fdim, fma, fmax, fmin, fmod, frexp, hypot, ldexp, nextafter, nexttoward, pow, remainder, remquo, scalbn, scalbln.

Примечание. Последний аргумент макросов frexp и remquo используется для записи результата, его тип может отличаться от остальных.

На основе типов аргументов выбирается вызываемая функция и, соответственно, тип возвращаемого значения. В C нет механизма перегрузки функций, однако выбор подходящей альтернативы при вызове соответствующего макроса всё же может быть реализован в конкретном компиляторе. Например, в MSVC CL для этого используется механизм generic selection. Если аргументы имеют разные типы, может быть выбрана неправильная функция, что, в свою очередь, может привести к непредсказуемому или неточному результату.

Рассмотрим пример:

#include <tgmath.h>

void first()
{
  float op1 = 15.61;
  float op2 = 31.4;
  float res = pow(op1, op2); //2.970643e+37
}

void second()
{
  double op1 = 15.61;
  float op2 = 31.4;
  float res = pow(op1, op2); //2.970645e+37
}

В приведённом коде аргументы макроса имеют типы разных размеров. В результате будут вызваны разные функции: float powf(float, float) в первом случае и double pow(double, double) — во втором. Логика выбора конкретной функции зависит от компилятора и не всегда прозрачна. К тому же, результат вычислений во втором примере будет неявно преобразован из типа double к типу float. Подобные преобразования в некоторых случаях могут привести к потере точности или немного разным результатам вычислений.

Избавиться от ошибки можно явно приведя аргументы к одинаковому типу. В таком случае после раскрытия макроса будет вызвана соответствующая функция и возвращаемое значение гарантированно будет иметь тип float, а результаты не будут отличаться.

Исправленный пример:

#include <tgmath.h>
 
void second()
{
  double op1 = 15.61;
  float op2 = 31.4;
  float res = pow((float)op1, op2); //2.970643e+37
}

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

  • MISRA-C-2023-21.23