Статически утверждают, что enum - это определенный базовый тип - PullRequest
0 голосов
/ 22 января 2019

MISRA 10.1 запрещает выполнение арифметики над объектом перечислимого типа.

Операнд по существу типа enum не должен использоваться в арифметической операции, поскольку объект перечисления использует целочисленный тип, определенный реализацией,Поэтому операция, включающая объект enum, может привести к результату с неожиданным типом.Обратите внимание, что константа перечисления из анонимного перечисления имеет по существу подписанный тип.

Они также предусматривают, что унарные операторы ++ и -- рассматриваются как двоичное сложение и вычитание для целей этого правила..

Если я использую целые числа в структуре управления циклом, мне все равно придется приводить их к перечислению позже, что нарушит правило 10.5

Значение выражения не должнобыть приведенным к неподходящему основному типу

Есть ли способ, которым я могу использовать статические утверждения, чтобы гарантировать некоторые предположения о базовом типе перечисления?Этот код может быть повторно использован в будущем на другой архитектуре.Я хотел бы в этом случае отклониться от 10,5 с уверенностью, что код выдаст ошибку времени компиляции, если будет допущено нарушение предположения о том, какой базовый тип перечисления.

Придуманный пример:

enum {thing1, thing2, ... , thing_max } thing_index_t
...
for(int thing_index = 0; thing_index < (int) thing_max; ++thing_index)
{
    init_something((thing_index_t) thing_index);
    //             ^~~~~~~~~~~~~~~~~~~~~~~~~
    // cannot cast a signed value to an enum type
    // [MISRA 2012 Rule 10.5, advisory]
}

Это всегда должно быть безопасным приведением, если я статически утверждаю, что sizeof(thing_index_t == int); и что thing1 == 0u верно?

Int всегда будет достаточно большим, чтобы вместить весь мой диапазон значений без повышения FWIW.

1 Ответ

0 голосов
/ 23 января 2019

Правило 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 и т. Д.

...