2015-08-10 8 views
2

На вопрос:Почему анонимное перечисление не удалось выполнить правило MISRA C 2012 10.3, а имя enum - нет?

Why do I have to cast an enum element when assigning it to a same enum variable type in C?

У меня были проблемы с этим кодом для проваливать MISRA C 2012 правило 10,3, который гласит:

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

Код это:

typedef enum 
{ 
    FLS_PROG_SUCCESS, 
    FLS_PROG_FAIL, 
    FLS_ERASE_SUCCESS2U, 
    FLS_ERASE_FAIL, 
    FLS_READ_SUCCESS, 
    FLS_READ_FAIL, 
    FLS_FORMAT_SUCCESS, 
    FLS_FORMAT_FAIL 
}FLS_JobResult_t; 

void Foo(void) 
{ 
    FLS_JobResult_t ProgramStatus; 

    /* Then I try to initialize the variable value */ 
    ProgramStatus = FLS_PROG_SUCCESS; 

    ... 
} 

И я принял ответ, что предположить, что этот инструмент может быть испорчен. Я до сих пор считаю, что, но дурачиться, пытаясь исправить, что я поставил имени к перечислениям декларации ЬурейиХ, которая в настоящее время является:

typedef enum FLS_JobResult_tag 
{ 
    FLS_PROG_SUCCESS, 
    FLS_PROG_FAIL, 
    FLS_ERASE_SUCCESS2U, 
    FLS_ERASE_FAIL, 
    FLS_READ_SUCCESS, 
    FLS_READ_FAIL, 
    FLS_FORMAT_SUCCESS, 
    FLS_FORMAT_FAIL 
}FLS_JobResult_t; 

И насколько я знаю, как это точно так же. Но тогда, сюрприз! Ошибка исчезла! Контроллер правил больше не отмечает, что это ошибка!

Затем делать некоторые исследования я нашел эти два вопроса:

What are the differences between these two typedef styles in C?

и

What's the difference between these two enum declarations - C?

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

Вопрос в следующем: В чем разница между анонимным enum и enum, который может нарушить правило 10.3 от MISRA c 2012?

+0

это не должно относиться к стандарту C, определенному ISO. он должен быть определен в указанном стандарте. – HuStmpHrrr

+0

Посмотрите определение MISRA «основного типа». Это отличается от фактического типа выражения в C. –

+0

Просто наблюдение: отладчики (по крайней мере, несколько, которые я использовал) имеют ту же проблему с именованными и неназванными структурами. Кажется, что внутренне * тип * объекта определяется тегом структуры или тегом enum, а typedef - просто псевдоним, используемый компилятором, но не отладчиком или контролером правил. – user3386109

ответ

3

Оба примера являются совместимыми и оба по тем же причинам: они не, назначая объект другого существенного типа.

Давайте проясним путаницу.

C предоставляет разработчикам/компиляторам большую свободу в своей системе типов, но также может привести к непреднамеренным результатам с возможностью потери ценности, знака или точности. MISRA-C: 2012 помогает обеспечить более безопасное типирование с его базовой моделью , которая обеспечивает рациональную основу для определений правил для управления использованием преобразований типов и повышения осведомленности о конкретном поведении (правила 10.x).

Модель основного типа заменяет модель «базового типа» стандарта MISRA-C: 2004 (что вызвало много трудностей с программистами, которые принуждали к ненужным приведениям по одной причине).

Я подозреваю, что ваш инструмент запутан и частично застрял в старой модели.

Правила незаменимого типа, которые относятся к перечислениям распознают два различных программ используют:

  1. объект типа перечислений, предназначенный, чтобы быть отличными от объекта с другого типа перечисления.
  2. перечисления - это общий способ хранения набора целочисленных констант.

Стандарт C не дает возможности различать эти виды использования. Поэтому MISRA-C: 2012 добавил следующие различных основных типов перечисления (в то время как не влияет на поведение C):

  1. Названный тип перечисления - перечисление определено в это идентифицируется либо тегом или typedef или используется в определении любого объекта, функции или типа; Приведение должно быть использовано, если требуется целое число значения константы перечисления.
  2. Анонимный тип перечисления - перечисление, которое не используется в определении любого объекта, функции или типа. Обычно это будет , используемый для определения набора констант, который может быть связан или не может быть связан, , но избегает необходимости в литье.

Пример анонимного типа перечислений:

enum {D = 10, E = 20, F = 30}; 

Оба ваши примеры названные типы перечислений (и они совместимы, потому что они такие же существенный тип). Другие примеры:

enum JOHN {A, B, C}; 
enum PAUL {E, F, G} PAUL; 

Таким образом, пример реального нарушения 10.3 будет:

enum PAUL bar = B; 

Ссылка: MISRA-C: 2012 Приложение D.5 «Эфирный тип перечислений» усиливает это очень хорошо с другими примерами.

+0

Большое спасибо !! – m4l490n

-1

это (почти) всегда плохая идея для typedef перечисления.

Гораздо лучше записать его следующим образом:

enum FLS_JobResult_t 
{ 
    FLS_PROG_SUCCESS, 
    FLS_PROG_FAIL, 
    FLS_ERASE_SUCCESS2U, 
    FLS_ERASE_FAIL, 
    FLS_READ_SUCCESS, 
    FLS_READ_FAIL, 
    FLS_FORMAT_SUCCESS, 
    FLS_FORMAT_FAIL 
}; 

void Foo(void) 
{ 
    enum FLS_JobResult_t ProgramStatus; 

    /* Then I try to initialize the variable value */ 
    ProgramStatus = FLS_PROG_SUCCESS; 

} 
+2

Можете ли вы объяснить, почему бы не напечатать его? И применяется ли это к 'struct'? –

+2

Вы могли бы разработать? почему это плохо? как насчет typedef структуры, союза или примитива? – HuStmpHrrr

+0

Хорошо, это хорошо, но здесь, в компании, одним из правил кодирования является то, что все структуры и перечисления объявляются как typedefs, а затем создают переменные из этих typedefs, чтобы использовать их. – m4l490n

3

С lside (type is anonymous enumeration) = rside (type is anonymous enumeration) слева и справа, не знает, что это же анонимное перечисление - следовательно, потенциальные проблемы.

С lside (type is named enumeration) = rside (type is _same_ named enumeration) - все в порядке, известно, что используется одно и то же перечисление.

1

Настоящая «ошибка» на самом деле находится в стандарте C (6.7.2.2).Перечисление константа гарантируется C, чтобы быть типа int, но перечисление переменной может быть нескольких различных типов, например char.

Что касается основного типа, который используется для констант перечисления и переменных перечисления, то он описан в приложении D.6 MISRA-C: 2012. Константы перечисления в вашем коде считаются одним и тем же существенным типом, что и с именем enum type.

Поэтому инструмент неправильный и не должен выдавать диагностику.