Функциональный макрос 'REPORT_ERROR', определенный [Директива MISRA 2012 4.9, рекомендация] - PullRequest
0 голосов
/ 24 сентября 2019

Я определил MACRO, который будет вызывать функцию и передавать аргумент.Получение ниже MISRA предупреждение для этого случая.Разве это не разрешено?Как этого избежать?

Каковы преимущества вызова функции (ей) в MACRO, как показано ниже?

#define REPORT_ERROR(Id, Error) ReportErr((uint16)21, (uint8)0, (uint8)Id, (uint8)Error)

void ReportErr(uint16 ModuleId, uint8 InstanceId, uint8 ApiId, uint8 ErrorId)
{

  // function - body

}

1 Ответ

4 голосов
/ 24 сентября 2019

Некоторые из правил MISRA-C являются «очень рекомендательными» до такой степени, что вы не можете их соблюдать и, возможно, захотите поднять постоянное отклонение от них.Одним из прекрасных примеров этого является правило против использования функционально-подобных макросов.

Каждый программист на Си знает, что функционально-подобные макросы плохие по многим обоснованным причинам.Но часто их просто нет.Таким образом, важность правила состоит в том, чтобы подтолкнуть к тому, что макросы, подобные функциональным, должны быть последним средством, в случае, если программисту каким-то образом это неизвестно.Правило не имеет практического применения.

В данном конкретном случае кажется, что макрос предназначен только для компенсации плохого API или плохого кода вызывающей стороны.Существует множество альтернативных способов решить эту проблему:

  • Сделать некоторые параметры функции необязательными, позволяя вызывающей стороне передавать значение NULL или подобное.
  • Использовать некоторый тип аргумента по умолчанию, установленный ввызывающий и выбирайте аргументы там в зависимости от варианта использования.
  • Ни в одном из вышеперечисленных вариантов нет опции, используйте отдельную функцию или встроенную функцию-обертку.

Другоевещи:

MISRA или без MISRA, у вас не должно быть «магических чисел» где-либо в вашем коде.Не должно быть магического числа 21 на ровном месте, его нужно заменить на константу.

Кроме того, вы должны использовать stdint.h вместо использования собственного гаражного стандарта для целочисленных типов.Если застряли с C90, используйте typedefs в пользовательском заголовке, соответствующем тем, что указаны в stdint.h.

...