|
Обьявление битовых полей |
|
|
|
Mar 10 2008, 15:28
|
Знающий
   
Группа: Свой
Сообщений: 526
Регистрация: 24-08-07
Из: Беларусь, Минск
Пользователь №: 30 045

|
Имею конструкцию: Код typedef union { struct { unsigned langID :2; unsigned unitsID :1; unsigned ED_Level1 :1; unsigned ED_Level2 :1; unsigned EDR_Level1 :1; unsigned EDR_Level2 :1; unsigned :0;
unsigned Al_Sound :2; unsigned Al_Light :1; unsigned Al_Vibro :1; unsigned :0;
unsigned Display :2; unsigned Backlight :2; unsigned Contrast :3; unsigned :0; }; unsigned char all[3]; } Settings_t; Settings_t settings; settings.all[0] = 0x00; settings.all[1] = 0x01; settings.all[2] = 0x02; Имеется стандарт: Цитата 6.7.2.1 Structure and union specifiers 11. A bit-field declaration with no declarator, but only a colon and a width, indicates an unnamed bit-field.105) As a special case, a bit-field structure member with a width of 0 indicates that no further bit-field is to be packed into the unit in which the previous bit-field, if any, was placed. Если я правильно понял стандарт, то байты будут начинаться с полей langID, Al_Sound и Display. Но это оказывается не так
Обьясните где я ошибся пожалуйста.
|
|
|
|
2 страниц
1 2 >
|
 |
Ответов
(1 - 15)
|
Mar 10 2008, 16:35
|
Знающий
   
Группа: Свой
Сообщений: 526
Регистрация: 24-08-07
Из: Беларусь, Минск
Пользователь №: 30 045

|
Цитата(Baser @ Mar 10 2008, 18:23)  А почему вы решили, что "unit" это один байт? На мой взгляд, unit это вся структура с битовыми полями. Я так не решал. Цитата(Baser @ Mar 10 2008, 18:23)  И нулевое битовое поле может находится только последним, чтобы не нужно было вычислять длину оставшейся части. А в вашем случае, все внутренние нулевые поля компилятор просто отбросил. А поле (Al_Sound :2;) расположил в следующем байте, потому что поля не могут пересекать границы машинного слова. Вот тут ка-раз и возникает вопрос. поле нулевой длинны может быть последним (тогда в чём его смысл?) или оно заполняет текущее слово до конца (следующее поле будет в начале следующего байта)?
|
|
|
|
|
Mar 10 2008, 16:50
|
Знающий
   
Группа: Свой
Сообщений: 526
Регистрация: 24-08-07
Из: Беларусь, Минск
Пользователь №: 30 045

|
Цитата(Baser @ Mar 10 2008, 18:47)  Посмотрел Кернигана, там действительно сказано, что: "Особая ширина, равная нулю, используется, когда требуется выйти на границу следующего слова." А какой компилятор и процессор? Компилятор MCC18 v3.16 не студенческая, процессор PIC18F65J50
|
|
|
|
|
Mar 10 2008, 17:08
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
Цитата(gotty @ Mar 10 2008, 18:50)  Компилятор MCC18 v3.16 не студенческая, процессор PIC18F65J50 А занесите в Al_Sound число 3 и посмотрите, в какие биты оно попадет. Судя по вашему рисунку этот компилятор просто не знает о специальном назначении битового поля нулевой ширины. Если биты попадут один в нулевой байт и второй в первый байт - так оно и есть - бага компилятора (если это не описано в его документации, тогда - фича). Остается только вручную сосчитать биты и заменить нулевую ширину поля на конкретную. Еще меня смущает размер этой структуры - unsigned - это unsigned int, int это обычно 2 байта, значит размер структуры должен бы быть или 2 или 4 байта, но три?
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Mar 10 2008, 17:12
|

Просто Che
    
Группа: Свой
Сообщений: 1 567
Регистрация: 22-05-07
Из: ExUSSR
Пользователь №: 27 881

|
Попробовал ваш пример в IAR AVR. Очень показательный пример, подтверждающий, что битовые поля это практически непереносимая конструкция в си. Обратите внимание: выравнивание идет по двум байтам и, соответственно, юнион с байтами накрывается медным тазом Вот еще из Кернигана: Цитата Почти все технические детали, касающиеся полей, в частности, возможность поля перейти границу слова, зависят от реализации.... На одних машинах поля размещаются слева направо, на других - справа налево. Это значит, что при всей полезности работы с ними, если формат данных, с которыми мы имеем дело, дан нам свыше, то необходимо самым тщательным образом исследовать порядок расположения полей; программы, зависящие от такого рода вещей, не переносимы.....
Эскизы прикрепленных изображений
|
|
|
|
|
Mar 10 2008, 18:47
|

Гуру
     
Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244

|
Цитата(Baser @ Mar 10 2008, 20:12)  подтверждающий, что битовые поля это практически непереносимая конструкция в си. Переносимая вполне, только надо аккуратно и тщательно расписывать структуры, возможно используя дополнительно вложенные структуры и унионы не брезговать и char, short, long и НЕ ИСПОЛЬЗОВАЬ int никогда. Насчет остального, несмотря на допустимость, разработчики большинства компиляторов думают одинаково.
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Mar 11 2008, 12:21
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
Цитата(gotty @ Mar 11 2008, 08:55)  Всё таки это недокументированная фича компилятора  Вероятно я криво выразился. Фича бывает только документированной. Если поведение отличается от предписанного стандартом и документировано - фича, если не документировано - бага или глюк (по вкусу) Цитата(gotty @ Mar 11 2008, 08:55)  так как в руководстве компилятора написано о невозможности полей пересекать границы байт. Интересно, как же он тогда резместит поле шириной, скажем, 15 бит? Или у вас в настройках где-то глубоко зарыт (и включен) ключик делать int шириной 1 байт, а в документации написано о невозможности пересекать границы базового типа?
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Mar 11 2008, 12:42
|
Знающий
   
Группа: Свой
Сообщений: 526
Регистрация: 24-08-07
Из: Беларусь, Минск
Пользователь №: 30 045

|
Цитата(Сергей Борщ @ Mar 11 2008, 14:21)  Интересно, как же он тогда резместит поле шириной, скажем, 15 бит? А компилятор отродясь не умеет делать поле шириной больше 8 бит (где-то видел в документации, и при компиляции выдаёт ошибку). Цитата(Сергей Борщ @ Mar 11 2008, 14:21)  Или у вас в настройках где-то глубоко зарыт (и включен) ключик делать int шириной 1 байт, а в документации написано о невозможности пересекать границы базового типа? А в документации написано о невозможности пересекать границы базового типа. Цитата(Baser @ Mar 11 2008, 12:48)  Так замените нулевые поля на конкретное число бит, дополняющих до целого байта (выровняйте вручную). Это должны понимать все компиляторы одинакого  Так и делаю, а что ещё остаётся.
|
|
|
|
|
Mar 11 2008, 14:35
|
Гуру
     
Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882

|
Цитата(gotty @ Mar 11 2008, 19:18)  Извиняюсь, но я до конца не понял Вашей идеи. Поясните пожалуйста. Идея в том, что Цитата A bit-field is interpreted as a signed or unsigned integer type consisting of the specified number of bits Это реплика к вашему Цитата(gotty) А компилятор отродясь не умеет делать поле шириной больше 8 бит (где-то видел в документации, и при компиляции выдаёт ошибку) Тип int на разных платформах может иметь различную ширину и в стандарте его размер явно не специфицирован. Лишь как ограничения на INT_MIN и INT_MAX, задаваемые в limits.h конкретной платформы.
|
|
|
|
|
Mar 11 2008, 14:44
|
Знающий
   
Группа: Свой
Сообщений: 526
Регистрация: 24-08-07
Из: Беларусь, Минск
Пользователь №: 30 045

|
Цитата(rezident @ Mar 11 2008, 16:35)  Тип int на разных платформах может иметь различную ширину и в стандарте его размер явно не специфицирован. Лишь как ограничения на INT_MIN и INT_MAX, задаваемые в limits.h конкретной платформы. Длинна int - не проблема, и не прблема в том что поле не может быть шире 8 бит, так как это чётко указано в руководстве компилятора, а в том что поле нулевой ширины интерпретируется неверно. P.S. Написал в службу поддержки Microchip, они со мной согласились и отправили "bug report" разработчикам.
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|