Говорит ли MISRA C 2012 не использовать bool

Я нахожусь на ранних стадиях создания материала для нового проекта.

Я определил функцию с возвращаемым типом "bool"

Я получил этот вывод от PC-Lint

    Including file sockets.h (hdr)
bool sock_close(uint8_t socket_id);
^
"LINT: sockets.h (52, 1) Note 970: Use of modifier or type '_Bool' outside of a typedef [MISRA 2012 Directive 4.6, advisory]"

Я пошел дальше и определил это в другом заголовке, чтобы закрыть lint:

typedef bool bool_t;

Тогда я начал задаваться вопросом, почему я должен был это сделать и почему это что-то изменило. Обратился к MISRA 2012 Dir 4.6. В основном это касается ширины примитивных типов, таких как short, int и long, их ширины и того, как они подписаны.

Стандарт не дает никакого расширения, рационального, исключения или примера для логического значения.

bool явно определен как _Bool в stdbool.h в C99. Так действительно ли этот критерий применим к bool?

Я думал, что _Bool явно всегда был «наименьшим стандартным целочисленным типом без знака, достаточно большим для хранения значений 0 и 1» в соответствии с разделом 6.2.5 C99. Итак, мы знаем, что bool не имеет знака. Значит, проблема в том, что _Bool не имеет фиксированной ширины, а тема каким-то образом продвигается? Потому что рациональное, казалось бы, противоречит этому понятию.

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

Как простое добавление typedef bool bool_t; что-то меняет, потому что я ничего не делаю, чтобы указать ширину или подписанность при этом? Ширина bool_t также будет зависеть от платформы. Есть ли лучший способ переопределить bool?

Тип не должен быть определен с определенной длиной, если только реализованный тип не имеет такой длины.

поэтому typedef bool bool8_t; должно быть совершенно незаконным.

Ошибается ли Gimpel в своей интерпретации Директивы 4.6 или они правы?


person Nick    schedule 02.06.2015    source источник
comment
_Bool — это собственный тип в C99, и для Misra вы не можете использовать собственный тип напрямую. Обычно это делается для переносимости кода. Иногда int имеет (со знаком) 32 бита, а иногда (со знаком) 16 бит, например, на 8-битных платформах. Таким образом, ваш код должен набирать s32 или s16 вместо того, чтобы окончательно уточнить ваши потребности.   -  person NGI    schedule 03.06.2015
comment
MISRA не запрещает использовать нативные типы. Директива 4.6 говорит, что вместо основных числовых типов следует использовать typedef, которые указывают размер и знак. Мой вопрос заключается в том, соответствует ли _Bool этому определению базового числового типа. Я просматриваю страницы 28-30 MISRA C 2012, и они ничего явно не говорят о bool - хотя они подробно говорят о typedefs в stdint.   -  person Nick    schedule 03.06.2015
comment
Одна точка данных: bool (определенный в <stdbool.h> — это макрос, который расширяется до _Bool, а не typedef. Ширина и подпись bool / _Bool не должны иметь значения, если вы используете их правильно; если MISRA действительно рекомендует не использовать его (в то время как разрешая ваш typedef), это кажется глупым.   -  person Keith Thompson    schedule 03.06.2015
comment
@KeithThompson Согласен, _Bool особенный, и его следует предпочесть typedef uint8_t bool_t;   -  person Nick    schedule 03.06.2015
comment
Похоже, что отсутствие <stdbool.h> и добавление typedef _Bool bool; сработает.   -  person Keith Thompson    schedule 03.06.2015
comment
@KeithThompson Lint не генерирует для этого никакого вывода. Но в этом есть какой-то запах кода. Я думаю, что это должно нарушать какое-то другое правило о переопределении зарезервированного символа. Я хотел бы знать, что не так с определением в stdbool. Проблема только в том, что это определение макроса, а не typedef? #define bool _Bool Как только все это будет сказано и сделано, я буду совершенно счастлив, используя typedef bool bool_t;, я просто хотел бы знать, зачем это нужно.   -  person Nick    schedule 03.06.2015
comment
@Nick: Я думаю, что PC-lint работает с предварительно обработанным источником (поэтому сообщение об ошибке относится к _Bool, а не к bool, которое появляется в источнике). Выбор C99 сделать bool макросом, а не typedef, ИМХО сомнительный. Лично я не хотел бы изобретать имя bool_t, а не использовать стандартное bool, даже если мне придется определять bool самому. Я мог бы сделать что-то вроде typedef _Bool bool; enum { false, true};, чтобы избежать использования макросов.   -  person Keith Thompson    schedule 03.06.2015
comment
В MISRA C:2012 нет ничего, что запрещало бы использование bool — это тоже неправильно! Кроме того, стандартная реализация bool в ISO C - это отдельная проблема.   -  person Andrew    schedule 20.06.2015


Ответы (2)


Использование модификатора или типа '_Bool' вне typedef [Директива MISRA 2012 4.6, рекомендательный]

Это ерунда, директива 4.6 касается только использования типов в stdint.h, а не int, short и т. д. Директива касается основных числовых типов. bool не имеет ничего общего с этой директивой, так как это не числовой тип.

По неизвестным причинам в примерах MISRA-C:2012 используется странный тип с именем bool_t, который не является стандартным. Но MISRA ни в коем случае не навязывает использование этого типа где бы то ни было, особенно они не навязывают его в директиве 4.6, в которой даже не упоминаются логические значения. MISRA нигде не рекомендует использовать bool или _Bool.

Gimpel ошибается в своей интерпретации Директивы 4.6?

Да, их инструмент дает неверную диагностику.

Кроме того, вам, возможно, придется настроить инструмент (если это возможно), чтобы сообщить ему, какой тип bool используется. В 5.3.2 упоминается, что вам, возможно, придется это сделать, если вы не используете _Bool, подразумевая, что все статические анализаторы должны понимать _Bool. Но даже если тип bool настроен правильно, dir 4.6 тут ни при чем.

person Lundin    schedule 03.06.2015
comment
Я просмотрел MISRA C 2012 в поисках ссылок на bool_t, и кажется, что они часто используются в качестве примера некоторого эффективного логического значения, которое не обязательно явно является _Bool. Я предполагаю, что это актуально для C90, и, возможно, MISRA попытались заставить свои примеры работать как для C99, так и для C90, поскольку они охватывают оба. - person Nick; 04.06.2015
comment
Служба поддержки Гимпеля также согласилась с тем, что это ложное срабатывание. Так что я просто собираюсь подавить примечание 970 о bool, используя -esym(970,_Bool) в файле lnt моего проекта. - person Nick; 05.06.2015
comment
Согласен - bool можно использовать. - person Andrew; 20.06.2015

Потенциальная проблема с булевыми типами заключается в том, что большая часть кода до C99 использовала однобайтовый тип для хранения значений true/false, и значительная его часть могла использовать имя «bool». Попытка сохранить любое число, кратное 256, в большинстве таких типов будет рассматриваться как сохранение нуля, в то время как сохранение ненулевого числа, кратного 256, в «bool» c99 даст 1. Если фрагмент кода, использующий «bool» C99, перенесенный в фрагмент кода, использующий байт с заданным типом, результирующий код может очень легко дать сбой (несколько менее вероятно, что код, написанный для байта с заданным типом, будет полагаться на какое-либо конкретное поведение при сохранении значения, отличного от 0 или 1). ).

person supercat    schedule 21.06.2016