реклама на сайте
подробности

 
 
> Обьявление битовых полей
msalov
сообщение Mar 10 2008, 15:28
Сообщение #1


Знающий
****

Группа: Свой
Сообщений: 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. Но это оказывается не так
Прикрепленное изображение

Обьясните где я ошибся пожалуйста.
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
Baser
сообщение Mar 10 2008, 16:23
Сообщение #2


Просто Che
*****

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



А почему вы решили, что "unit" это один байт? На мой взгляд, unit это вся структура с битовыми полями. И нулевое битовое поле может находится только последним, чтобы не нужно было вычислять длину оставшейся части.
А в вашем случае, все внутренние нулевые поля компилятор просто отбросил.
А поле (Al_Sound :2;) расположил в следующем байте, потому что поля не могут пересекать границы машинного слова.
Go to the top of the page
 
+Quote Post
msalov
сообщение Mar 10 2008, 16:35
Сообщение #3


Знающий
****

Группа: Свой
Сообщений: 526
Регистрация: 24-08-07
Из: Беларусь, Минск
Пользователь №: 30 045



Цитата(Baser @ Mar 10 2008, 18:23) *
А почему вы решили, что "unit" это один байт? На мой взгляд, unit это вся структура с битовыми полями.
Я так не решал.
Цитата(Baser @ Mar 10 2008, 18:23) *
И нулевое битовое поле может находится только последним, чтобы не нужно было вычислять длину оставшейся части.
А в вашем случае, все внутренние нулевые поля компилятор просто отбросил.
А поле (Al_Sound :2;) расположил в следующем байте, потому что поля не могут пересекать границы машинного слова.
Вот тут ка-раз и возникает вопрос. поле нулевой длинны может быть последним (тогда в чём его смысл?) или оно заполняет текущее слово до конца (следующее поле будет в начале следующего байта)?
Go to the top of the page
 
+Quote Post
Baser
сообщение Mar 10 2008, 16:47
Сообщение #4


Просто Che
*****

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



Цитата(gotty @ Mar 10 2008, 18:35) *
Вот тут ка-раз и возникает вопрос. поле нулевой длинны может быть последним (тогда в чём его смысл?) или оно начинает новое слово (следующий байт)?

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

А какой компилятор и процессор?
Go to the top of the page
 
+Quote Post
msalov
сообщение Mar 10 2008, 16:50
Сообщение #5


Знающий
****

Группа: Свой
Сообщений: 526
Регистрация: 24-08-07
Из: Беларусь, Минск
Пользователь №: 30 045



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

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

Компилятор MCC18 v3.16 не студенческая, процессор PIC18F65J50
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Mar 10 2008, 17:08
Сообщение #6


Гуру
******

Группа: Модераторы
Сообщений: 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)
Go to the top of the page
 
+Quote Post
msalov
сообщение Mar 11 2008, 06:55
Сообщение #7


Знающий
****

Группа: Свой
Сообщений: 526
Регистрация: 24-08-07
Из: Беларусь, Минск
Пользователь №: 30 045



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

Al_Sound попадает на начало байта, так как в руководстве компилятора написано о невозможности полей пересекать границы байт. А вот про поле нулевой ширины ничего не сказано crying.gif
Всё таки это недокументированная фича компилятора 07.gif
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Mar 11 2008, 12:21
Сообщение #8


Гуру
******

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



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


Цитата(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)
Go to the top of the page
 
+Quote Post
msalov
сообщение Mar 11 2008, 12:42
Сообщение #9


Знающий
****

Группа: Свой
Сообщений: 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) *
Так замените нулевые поля на конкретное число бит, дополняющих до целого байта (выровняйте вручную). Это должны понимать все компиляторы одинакого smile.gif
Так и делаю, а что ещё остаётся.
Go to the top of the page
 
+Quote Post
rezident
сообщение Mar 11 2008, 13:46
Сообщение #10


Гуру
******

Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882



Цитата(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.
Go to the top of the page
 
+Quote Post
msalov
сообщение Mar 11 2008, 14:18
Сообщение #11


Знающий
****

Группа: Свой
Сообщений: 526
Регистрация: 24-08-07
Из: Беларусь, Минск
Пользователь №: 30 045



Цитата(rezident @ Mar 11 2008, 15:46) *
Извиняюсь, что вмешиваюсь, но в стандарте ANSI C сказано

Извиняюсь, но я до конца не понял Вашей идеи. Поясните пожалуйста.
Go to the top of the page
 
+Quote Post

Сообщений в этой теме


Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 11th August 2025 - 12:02
Рейтинг@Mail.ru


Страница сгенерированна за 0.01498 секунд с 7
ELECTRONIX ©2004-2016