Может ли enum C typedef принимать значение больше, чем количество элементов в перечислении?

Я просматриваю много кода, который выглядит так

typedef enum {
    OPTION1
    OPTION2
} option_t

...

void a_function(option_t option){
    if (option == OPTION1){
        ...
    } else if (option == OPTION2){
        ...
    } else {
        // report an error!
        // can we ever get here?
    }
}

Мой вопрос: нужно ли предложение else, которое сообщает об ошибке? Мне кажется, что, поскольку option имеет тип option_t, перечисление, которое имеет только 2 возможности, для option не должно быть никакого значения, кроме OPTION1 и OPTION2, поэтому должно быть невозможно выполнение предложения else. .

Что помешает вызывающему абоненту передать -1 или 4711 вашей функции?

Gerhardh 22.02.2023 12:45

@Gerhardh знает компилятор? Кажется, что option быть option_t вместо int должно предотвратить это?

ACarter 22.02.2023 12:46

enum в основном просто определяет имена для постоянных значений. Он не указывает для них конкретный целочисленный тип (со знаком или без знака, короткий или длинный,...) и не устанавливает некоторые ограничения.

Gerhardh 22.02.2023 12:48

Касательно «Может ли enum typedef в C принимать значение, превышающее количество элементов в перечислении?»: это не тот вопрос, который вы хотите задать; enum foo { a = 12 } имеет значение больше, чем количество его именованных членов.

Eric Postpischil 22.02.2023 14:02
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
4
57
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Перечисления не очень важны для безопасности типов и, как правило, нарушаются типом дизайна (на сегодняшний день грядущий C23 изменит многие дефекты языка C). В вашем примере OPTION1 имеет тип int, а option_t имеет некоторый целочисленный тип, достаточно большой, чтобы соответствовать всем значениям в списке перечисления, не обязательно int.

Мой вопрос в том, нужно ли предложение else, которое сообщает об ошибке?

Это то, что известно как «защитное программирование». Теоретически перечисление не должно иметь никаких других значений. На практике ничто не мешает вам присвоить ему любое целочисленное значение. Или в случае багов с повреждением памяти ничто не мешает багу изменить его на другое значение.

Так что это зависит от ваших требований. Для коммерческих / любительских / требований к ПК else, вероятно, не требуется. Для связанного с безопасностью, критически важного или аналогичного программного обеспечения (например, соответствия MISRA C) требуется else и надлежащая практика.

Пост по теме: Как создать безопасное перечисление типов?

Вместо этого я использую unums, если #define по одной причине. Отладчики отображают имена перечислений, что упрощает отладку.

0___________ 22.02.2023 14:26

В стандарте C это не указано явно, но каждый перечисляемый тип на самом деле является некоторым обычным целочисленным типом. Хотя C 2018 6.12.5 16 говорит: «… Каждое отдельное перечисление представляет собой отдельный перечисляемый тип», 6.7.2.2 4 говорит: «Каждый перечисляемый тип должен быть совместим с char, целочисленным типом со знаком или целочисленным типом без знака. Выбор типа определяется реализацией, но он должен быть способен представлять значения всех членов перечисления…»

Ни в одном из них не ясно, какие значения могут быть представлены в перечисляемом типе или определено ли поведение для значений, не входящих в число именованных значений перечисления — утверждение, что два типа совместимы, не является утверждением, что все значения одного типа представимы. по другому типу.

Другие вопросы по теме