DetSimen и битовые поля
- Войдите на сайт для отправки комментариев
Пнд, 15/10/2018 - 13:37
Всё-таки в С я плаваю. И не просто плаваю, а плаваю как утяжеленный топор без ручки с привареным урановым ломом.
В одном праэктике есть структура с битовыми полями, один из байтиков которой описан как
bool SWP1 : 1; // установить software port 1 в 0/1 (в китайских модулях вещь бесполезная) bool MuteLeft : 1; // выключить левый канал bool MuteRight : 1; // выключить правый канал bool Mono : 1; // Установить принудительно режим Моно enumHSLI HSLI : 1; // High/Low Side Injection = false/true Low = true enumSearchStopLevel AutoSearchLevel : 2; // уровень сигнала станции для остановки автопоиска bool SearchUp : 1; // true - автопоиск будет искать вверх по частоте, false - вниз
enum-ы описаны как
enum class enumHSLI: bool {HiSide=false, LowSide=true}; // High/Low side injection гетеродин выше/ниже несущей
//--------------------------------------------------------------------------------
// уровень сигнала станции для остановки автопоиска
//
// Not Allowed - запрещенная комбинация
// Leak - поиск станций с низким уровнем сигнала
// Medium - поиск станций со средним уровнем сигнала
// Strong - поиск только сильных, ближайших станций
enum class enumSearchStopLevel: uint8_t {NotAllowed=0, Leak=1, Medium=2, Strong=3};
всё компилируеца, канеш, но анажды, что-то подсказало мне включить warning-и при компиляции. Теперь битовые поля, описанные как bool, и даже enumHSLI вопросов не вызывает, а на enumSearchStopLevel канпилятор ругаеца от так
warning: 'T5767Output::AutoSearchLevel' is too small to hold all values of 'enum class enumSearchStopLevel
enumSearchStopLevel AutoSearchLevel *: 2;
и вроде бы 2 бита хватает, чтобы хранить значения от 0 до 3, пошто канпилятор такой суровый? Какие ошибки меня ждут при таком использовании enum class и как избавить меня от этих warning-ов.
enum-ы описаны как
enum class enumSearchStopLevel: uint8_t {NotAllowed=0, Leak=1, Medium=2, Strong=3};конечно too smal - ты ж enum описал размером в uint8_t
конечно too smal - ты ж enum описал размером в uint8_t
дак а по другому не опишешь, или опишешь? Тогда как?
если написать , допустим
uint8_t SignalLevel:4;
то все будет намайно, без ошибок, значения будуть 0-15, хотя тип тоже описан как целый байт
Поискал в СтекОверфлоу - пишут. что эта проблема решения не имеет?
"in C it is an undefined behavior, because a bit-field can only have signed int or unsigned int or bool types"
мда.
Для того, чтобы тебе правильно вписаться в структуру, нужен enum в 2 бита. Но размерность enum может задаваться только базовыми типами, самый маленький из которых - 8 бит.
Так что или enum на 8 бит или 2 бита и дефайны.
Дед, во многих знаниях, много печали. Вот будь на Вашем месте кто-то, действительно плохо знающий язык (а не прибедняющийся, как Вы), у него бы не было проблем потому, что он не стал бы делать типизированный enum, а для нетипизированного этой проблемы не возникает от слова совсем - компилятор сам разбирается с его размером.
Вот смотрите:
enum class enumHSLI: bool {HiSide=false, LowSide=true}; // High/Low side injection гетеродин выше/ниже несущей enum enumSearchStopLevel {NotAllowed=0, Leak=1, Medium=2, Strong=3}; union MyUnion { uint8_t byteBase; struct { bool SWP1 : 1; // установить software port 1 в 0/1 (в китайских модулях вещь бесполезная) bool MuteLeft : 1; // выключить левый канал bool MuteRight : 1; // выключить правый канал bool Mono : 1; // Установить принудительно режим Моно enumHSLI HSLI : 1; // High/Low Side Injection = false/true Low = true enumSearchStopLevel AutoSearchLevel : 2; // уровень сигнала станции для остановки автопоиска bool SearchUp : 1; }; }; void setup(void){ Serial.begin(57600); Serial.print("sizeof(MyUnion)="); Serial.println(sizeof(MyUnion)); // MyUnion kaka; kaka.byteBase = 0; kaka.AutoSearchLevel = Strong; Serial.print("kaka="); Serial.println(kaka.byteBase, HEX); } void loop(void){}Никаких предупреждений - всё пучком. Результат
Так что всё правильно работает.
Причем, заметьте (это важно!) компилятор именно разбирается, а не просто "плюёт на возможную ошибку"! В этом легко убедиться - достаточно в строке 2 перед "}" добавить, например, ", EvenStronger=4". После этого двухбитовое поле реально окажется маленьким и сообщение, о котором Вы говорили, появится вновь. Так что он реально смотрит и предупреждает.
Спасибо за науку.
Просто чем хорош типизированный enum, тем, что его константы имеют область видимости, ограниченную внутри самого enum-а. Т.е два или три или больше enum-ов в одном файле могут иметь одинаково поименованные константы внутри себя, что в обычных enum-ах, нетипизированных, вопщем-та, не допускаеца (но это не точно). Обращение, конечно, к типизированному enum-у приходится писать дольше, зато перепутать константы, относящиеся к разным enum-ам нельзя.
В кристально чесном С, которого полно у Onkel-я, я этого не помню, памойму это уже позднее благоприобретение, слизанное с Шарпа. Но вот почему бы не сделать еще шажок, чтоб срастить эту удобную канструкцию с битовыми полями... Ну это я так, ворчу.
В любом случае, спасибо ЕвгенийП, информацию я впитал. :) Буду воспринимать это как данность, правда, с горестным недоумением. (и штозаязыктакой, и кто его только придумал, и где сечас эти люди? ну и по традиции, наданапица)
А так?
typedef enum {NotAllowed, Leak, Medium, Strong} enumSearchStopLevel;Мож не Leak, а Weak ? Тока щас увидел.
Мож не Leak, а Weak ? Тока щас увидел.
Leak - тоже ничего, "утечка" - "слабенько" :-)))
Не придирайтесь к словам.)
Еще как! Особенно в контексте to take a leak -- справить малую нужду. :) Варианты leak/medium/strong в этом случае порождают какие-то неуловимые ассоциации. :)
Еще как! Особенно в контексте to take a leak -- справить малую нужду. :) Варианты leak/medium/strong в этом случае порождают какие-то неуловимые ассоциации. :)
Ничего не отменял. Как и в русском, одно и то же там можно выразить по разному. По поводу нюансов, прошу в гугл.