статическая встроенная функция в файле заголовка и проблема с правилом 8.5.

Я использую микроконтроллер «IAR RL78» и «RL78-R5F10BGG». Я также включил MISRA C 2004 в IAR.

Я хочу определить одну из моих функций как «встроенную». Эта встроенная функция должна использоваться в различных файлах c. Итак, я определил функцию в одном из своих

файлы заголовков и включите этот файл заголовка во все файлы c, которым нужна функция. Но моя проблема связана с правилом MISRA C 8.5 после компиляции. Он говорит:

Ошибка [Pm123]: в файле заголовка не должно быть определения объектов или функций (правило 8.5 MISRA C 2004)

Ниже приводится определение встроенной функции в заголовке common.h:

static inline int16u SET_BIT(int16u int16uVar, int16u int16uBitIndex);

#pragma inline=forced
static inline int16u SET_BIT(int16u int16uVar, int16u int16uBitIndex)
{
     int16uVar |= ( (int16u)1u << (int16uBitIndex) );

     return int16uVar ;
}

В чем проблема?

Есть ли способ избавиться от этой проблемы?


person Anmk    schedule 20.05.2020    source источник
comment
В: Что такое int16u? Суффикс u означает беззнаковый? В таком случае вы хотите использовать uint16_t из ‹stdint.h›?   -  person Razzle    schedule 15.12.2020


Ответы (3)


MISRA-C: 2004 не распространяется на C99, поэтому вы просто не можете использовать inline вообще.

И из-за этого правило об определениях функций в файлах заголовков прямо действует даже на встроенные функции. Невозможно согласовать MISRA-C: 2004 с опубликованным кодом - вам придется создавать отклонения от нескольких обязательных правил.


Я рекомендую перейти на MISRA-C: 2012, в котором есть явное исключение для этого сценария (правило 5.9):

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

MISRA-C: 2012 также требует, чтобы все встроенные функции были объявлены как static (правило 8.10).

MISRA-C: 2012 - намного лучший документ почти во всех отношениях. IAR также поддерживает версию 2012 года, и их средство проверки MISRA должно быть отдельным плагином, не связанным с конкретным MCU.


Не имеющий отношения к вашему актуальному вопросу (int16u)1u << совершенно неверен и опасен.

Если вы действительно должны иметь подписанные типы (чаще всего нет), тогда вы должны сначала выполнить сдвиг на беззнаковом типе, затем преобразовать в подписанный.

Это необходимо не только для соответствия MISRA-C, но и для исправления явной ошибки C, которая вызывает неопределенное поведение на 8- и 16-битных микроконтроллерах, когда вы оставляете данные сдвига в знаковый бит.

Правильный код должен быть int16uVar |= (int16u)(1u << int16uBitIndex);, и я считаю, что это также удовлетворяет требованиям MISRA-C: 2004 о приведении к базовому типу после операции.


Также обратите внимание, что создание собственных "стандартных" целочисленных типов не одобряется в целом - поскольку вы используете C99, вам следует использовать stdint.h и ничего больше. Это также рекомендация MISRA-C: 2012.

person Lundin    schedule 20.05.2020
comment
MISRA-C на самом деле является стандартом автомобильной промышленности, и, поскольку AUTOSAR становится все более и более принятым, такие типы, как uint8 / sint8, uint8 / uint16 ... фактически определены в Platform_Types.h (включены в Std_Types.h). который на самом деле следует использовать вместо компилятора stdint.h. И во-вторых, это не C-Bug, а определение языка C и его абстрактной машины того, как работают побитовые операции (включая impl-defined и undefined поведение), и это не только 8/16-битные микроконтроллеры, но и 32-битные микроконтроллеры. - person kesselhaus; 22.05.2020
comment
@kesselhaus Нет, это не так. ISO C более каноничен, чем MISRA-C, который более каноничен, чем AUTOSAR. Кроме того, прошло много времени с тех пор, как MISRA-C предназначалась только для автомобилей. В настоящее время его используют все, даже вне встроенных систем. Что касается сдвига влево, это опасно и не определено только в том случае, если вы либо сдвинете отрицательные числа, либо если вы сдвинете данные в знаковый бит числа со знаком. Это означает, что для переменной со знаком 16 сдвиг влево 15 или более бит всегда является ошибкой. Приведение типа без знака к типу со знаком, как я думал, весьма сомнительно. Код, вызывающий неопределенное поведение = ошибка. - person Lundin; 25.05.2020
comment
В частности, в автомобильной отрасли почти любой OEM-производитель сейчас запрашивает AUTOSAR, и, по крайней мере, поставщики Tier1 идут по пути, если им приходится поддерживать несколько OEM-производителей. Здесь stdint.h используется и НЕ ДОЛЖЕН использоваться напрямую. И, кстати, у 32-битных микроконтроллеров такая же проблема с sint32. А подписанный сдвиг влево определяется как неопределенное поведение и поведение, определяемое реализацией сдвига вправо со знаком. И да, MISRA-C к настоящему времени может использоваться и вне автомобильной промышленности (я только что догадался по MISRA-C об авромоторной среде здесь) - person kesselhaus; 27.05.2020

Спасибо, Лундин, за полезный ответ. Что касается второй части вашего ответа, я должен сказать, что в нашем стиле кодирования мы используем int16u для неподписанных типов int. это

typedef unsigned int int16u

Итак, я переключаю беззнаковое int на подписанное int. в моем вопросе есть опечатка, то есть я написал

int16uVar |= ( (int16u)1u << (int16uBitIndex) );

но правильная строка в моем коде

int16uVar |= ( (int16u)1 << (int16uBitIndex) );

Я действительно сожалею.

person Anmk    schedule 20.05.2020
comment
Ух ты, правда, не стоит так называть своих типов. int16_t против int16u, легко перепутать. В любом случае приведение должно быть после сдвига для базового типа MISRA-C: 2004. - person Lundin; 20.05.2020

Проще говоря, inline не является частью C90 (согласно MISRA C: 2004)

Однако есть обходной путь, если вы примете соответствие требованиям MISRA. ... здесь представлена ​​концепция разрешений на отклонение, и команда MISRA удобно предоставит вам такое разрешение на использование inline (Permit / MISRA / C: 2004 / 1.1.C.1)

Конечно, большинство компиляторов в любом случае просто игнорируют встроенный квалификатор ...

Декларация интересов: см. Профиль!

person Andrew    schedule 21.05.2020