Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Обьявление битовых полей
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему
msalov
Имею конструкцию:
Код
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. Но это оказывается не так
Нажмите для просмотра прикрепленного файла
Обьясните где я ошибся пожалуйста.
Baser
А почему вы решили, что "unit" это один байт? На мой взгляд, unit это вся структура с битовыми полями. И нулевое битовое поле может находится только последним, чтобы не нужно было вычислять длину оставшейся части.
А в вашем случае, все внутренние нулевые поля компилятор просто отбросил.
А поле (Al_Sound :2;) расположил в следующем байте, потому что поля не могут пересекать границы машинного слова.
msalov
Цитата(Baser @ Mar 10 2008, 18:23) *
А почему вы решили, что "unit" это один байт? На мой взгляд, unit это вся структура с битовыми полями.
Я так не решал.
Цитата(Baser @ Mar 10 2008, 18:23) *
И нулевое битовое поле может находится только последним, чтобы не нужно было вычислять длину оставшейся части.
А в вашем случае, все внутренние нулевые поля компилятор просто отбросил.
А поле (Al_Sound :2;) расположил в следующем байте, потому что поля не могут пересекать границы машинного слова.
Вот тут ка-раз и возникает вопрос. поле нулевой длинны может быть последним (тогда в чём его смысл?) или оно заполняет текущее слово до конца (следующее поле будет в начале следующего байта)?
Baser
Цитата(gotty @ Mar 10 2008, 18:35) *
Вот тут ка-раз и возникает вопрос. поле нулевой длинны может быть последним (тогда в чём его смысл?) или оно начинает новое слово (следующий байт)?

Посмотрел Кернигана, там действительно сказано, что:
"Особая ширина, равная нулю, используется, когда требуется выйти на границу следующего слова." rolleyes.gif

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

А какой компилятор и процессор?

Компилятор MCC18 v3.16 не студенческая, процессор PIC18F65J50
Сергей Борщ
Цитата(gotty @ Mar 10 2008, 18:50) *
Компилятор MCC18 v3.16 не студенческая, процессор PIC18F65J50
А занесите в Al_Sound число 3 и посмотрите, в какие биты оно попадет. Судя по вашему рисунку этот компилятор просто не знает о специальном назначении битового поля нулевой ширины. Если биты попадут один в нулевой байт и второй в первый байт - так оно и есть - бага компилятора (если это не описано в его документации, тогда - фича). Остается только вручную сосчитать биты и заменить нулевую ширину поля на конкретную. Еще меня смущает размер этой структуры - unsigned - это unsigned int, int это обычно 2 байта, значит размер структуры должен бы быть или 2 или 4 байта, но три?
Baser
Попробовал ваш пример в IAR AVR. Очень показательный пример, подтверждающий, что битовые поля это практически непереносимая конструкция в си. Обратите внимание: выравнивание идет по двум байтам и, соответственно, юнион с байтами накрывается медным тазом smile.gif

Вот еще из Кернигана:
Цитата
Почти все технические детали, касающиеся полей, в частности, возможность поля перейти границу слова, зависят от реализации....
На одних машинах поля размещаются слева направо, на других - справа налево. Это значит, что при всей полезности работы с ними, если формат данных, с которыми мы имеем дело, дан нам свыше, то необходимо самым тщательным образом исследовать порядок расположения полей; программы, зависящие от такого рода вещей, не переносимы.....
zltigo
Цитата(Baser @ Mar 10 2008, 20:12) *
подтверждающий, что битовые поля это практически непереносимая конструкция в си.

Переносимая вполне, только надо аккуратно и тщательно расписывать структуры, возможно используя дополнительно вложенные структуры и унионы не брезговать и char, short, long и НЕ ИСПОЛЬЗОВАЬ int никогда. Насчет остального, несмотря на допустимость, разработчики большинства компиляторов думают одинаково.
msalov
Цитата(Сергей Борщ @ Mar 10 2008, 19:08) *
А занесите в Al_Sound число 3 и посмотрите, в какие биты оно попадет. Судя по вашему рисунку этот компилятор просто не знает о специальном назначении битового поля нулевой ширины. Если биты попадут один в нулевой байт и второй в первый байт - так оно и есть - бага компилятора (если это не описано в его документации, тогда - фича). Остается только вручную сосчитать биты и заменить нулевую ширину поля на конкретную. Еще меня смущает размер этой структуры - unsigned - это unsigned int, int это обычно 2 байта, значит размер структуры должен бы быть или 2 или 4 байта, но три?

Al_Sound попадает на начало байта, так как в руководстве компилятора написано о невозможности полей пересекать границы байт. А вот про поле нулевой ширины ничего не сказано crying.gif
Всё таки это недокументированная фича компилятора 07.gif
Baser
Цитата(gotty @ Mar 11 2008, 08:55) *
А вот про поле нулевой ширины ничего не сказано
Всё таки это недокументированная фича компилятора

Так замените нулевые поля на конкретное число бит, дополняющих до целого байта (выровняйте вручную). Это должны понимать все компиляторы одинакого smile.gif
Сергей Борщ
Цитата(gotty @ Mar 11 2008, 08:55) *
Всё таки это недокументированная фича компилятора 07.gif
Вероятно я криво выразился. Фича бывает только документированной. Если поведение отличается от предписанного стандартом и документировано - фича, если не документировано - бага или глюк (по вкусу) smile3046.gif


Цитата(gotty @ Mar 11 2008, 08:55) *
так как в руководстве компилятора написано о невозможности полей пересекать границы байт.
Интересно, как же он тогда резместит поле шириной, скажем, 15 бит? Или у вас в настройках где-то глубоко зарыт (и включен) ключик делать int шириной 1 байт, а в документации написано о невозможности пересекать границы базового типа?
msalov
Цитата(Сергей Борщ @ Mar 11 2008, 14:21) *
Интересно, как же он тогда резместит поле шириной, скажем, 15 бит?
А компилятор отродясь не умеет делать поле шириной больше 8 бит (где-то видел в документации, и при компиляции выдаёт ошибку).
Цитата(Сергей Борщ @ Mar 11 2008, 14:21) *
Или у вас в настройках где-то глубоко зарыт (и включен) ключик делать int шириной 1 байт, а в документации написано о невозможности пересекать границы базового типа?
А в документации написано о невозможности пересекать границы базового типа.
Цитата(Baser @ Mar 11 2008, 12:48) *
Так замените нулевые поля на конкретное число бит, дополняющих до целого байта (выровняйте вручную). Это должны понимать все компиляторы одинакого smile.gif
Так и делаю, а что ещё остаётся.
rezident
Цитата(gotty @ Mar 11 2008, 17:42) *
А компилятор отродясь не умеет делать поле шириной больше 8 бит (где-то видел в документации, и при компиляции выдаёт ошибку).
Извиняюсь, что вмешиваюсь, но в стандарте ANSI C сказано
Цитата
6.7.2.1 Structure and union specifiers
...
9 A bit-field is interpreted as a signed or unsigned integer type consisting of the specified
number of bits.104) If the value 0 or 1 is stored into a nonzero-width bit-field of type
_Bool, the value of the bit-field shall compare equal to the value stored.
10 An implementation may allocate any addressable storage unit large enough to hold a bit-
field. If enough space remains, a bit-field that immediately follows another bit-field in a
structure shall be packed into adjacent bits of the same unit. If insufficient space remains,
whether a bit-field that does not fit is put into the next unit or overlaps adjacent units is
implementation-defined. The order of allocation of bit-fields within a unit (high-order to
low-order or low-order to high-order) is implementation-defined. The alignment of the
addressable storage unit is unspecified.
msalov
Цитата(rezident @ Mar 11 2008, 15:46) *
Извиняюсь, что вмешиваюсь, но в стандарте ANSI C сказано

Извиняюсь, но я до конца не понял Вашей идеи. Поясните пожалуйста.
rezident
Цитата(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 конкретной платформы.
msalov
Цитата(rezident @ Mar 11 2008, 16:35) *
Тип int на разных платформах может иметь различную ширину и в стандарте его размер явно не специфицирован. Лишь как ограничения на INT_MIN и INT_MAX, задаваемые в limits.h конкретной платформы.

Длинна int - не проблема, и не прблема в том что поле не может быть шире 8 бит, так как это чётко указано в руководстве компилятора, а в том что поле нулевой ширины интерпретируется неверно.

P.S. Написал в службу поддержки Microchip, они со мной согласились и отправили "bug report" разработчикам.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.