Правило 10.5 является общим звуком, но контролируемые преобразования из enum
в подписанные / неподписанные не опасны.MISRA обеспокоены тем, что у вас может быть перечисление типа enum {thing1=123, thing2=456, ...
.Но если вы знаете, что константы перечислителя имеют значения от 0 до max, тогда в большинстве случаев безопасно переходить к целым числам и обратно.
Вам не нужно формальное отклонение для консультативных правил.Я бы предпочел оставить комментарий, такой как
/* Violates MISRA 10.5 but iterating from thing1 to thing_num is safe.
Integer type is used since arithmetic on enums is forbidden by 10.1. */
(или использовать тот процесс, который у вас есть для работы с консультативными правилами.)
Что касается статических утверждений, sizeof(thing_index_t == int)
ничего не доказывает, так как допустимые значения константы перечисления имеют значение.И thing1 == 0u
гарантируется стандартом C, поэтому вам не нужно утверждать это.
Статическое утверждение для обеспечения целостности перечисления должно выглядеть скорее как
#define THING_VALUES \
thing1, \
thing2, \
thing_num \
typedef enum { thing1=123, thing2=456, thing_num } thing_index_t;
const size_t expected_size = sizeof((thing_index_t[]){ THING_VALUES }) / sizeof(thing_index_t);
_Static_assert( thing_num+1 == expected_size );
, где составной литерал(thing_index_t[]){ THING_VALUES })
получает размер, соответствующий количеству констант перечисления в списке.expected_size
- количество предметов.Это утверждает, что никаких специальных инициализаторов, таких как thing1=123
, нет.
Единственная дыра в петле - это что-то экзотическое, например thing1=123, thing2=1
, которое это не поймает.Чтобы защититься от этого, вам нужно пойти еще дальше с макросами, реализовав все это с помощью макросов X и т. Д.