Битовые поля структура присваивания неожиданное поведение

Я не знаю почему, но назначение битовых полей не работает должным образом. Возможно, это просто глупость, но я не смог найти проблему.

Любая помощь приветствуется.

<code>typedef struct  a {
    unsigned char a1 :1;
    unsigned char a2 :3;
    unsigned char a3 :2;
    unsigned char a4 :2;
} __attribute__((packed)) mystruct;

int main() {
    mystruct d;
    d.a1 = 0;
    d.a2 = 2;
    d.a3 = 1;
    d.a4 = 2;

    unsigned char *val = (unsigned char*) &d;

    printf("%02X \n", *val);
    printf("%02X \n", sizeof(hola));

    exit(0);
}
</code>

возвращаемый результат:

<code>94
01
</code>

ожидаемый результат:

<code>26
01
</code>
 keety12 апр. 2012 г., 18:52
@James, если вначале был MSB, а затем LSB, то 0x26
 Jonathan Leffler16 июн. 2013 г., 08:04
Что такоеhola тотsizeof(hola) печатает 1? В C99 формат, используемый для печатиsize_t должно быть%02zX; в C89 нет надежного способа справиться с этим (вот почемуz модификатор был добавлен в C99), но вы могли бы привести результатsizeof(hola) вint поскольку%02X ожидает напечататьint, На 64-битном компьютере с прямым порядком байтов вы можете получить нулевой размер.
 James12 апр. 2012 г., 18:50
0x94 правильно. почему вы ожидаете 0x26?
 Thomas Matthews12 апр. 2012 г., 21:28
Я предлагаю вам использовать двоичные арифметические операторы, если битовое размещение является проблемой. Он более переносим, и, как вы можете видеть, использование структуры для преобразования битовых полей определяется реализацией (не согласовано).
 KevinDTimm12 апр. 2012 г., 18:49
ожидаемые результаты от битовых полей часто не то, что вы ожидаете. а не проверять весь свой код, я спрошу, учли ли вы все порядковые номера вашей платформы?

Ответы на вопрос(2)

  MSB                                LSB
+----+----+----+----+----+----+----+----+
|a4.1|a4.0|a3.1|a3.0|a2.2|a2.1|a2.0| a1 |
+----+----+----+----+----+----+----+----+
| 1  | 0  | 0  | 1  | 0  | 1  | 0  | 0  |
+----+----+----+----+----+----+----+----+
|        0x9        |        0x4        |
+----+----+----+----+----+----+----+----+

Как уже отмечалось, поведение определяется реализацией; это один из двух законных способов организации данных, и, похоже, это формат, выбранный на вашем компьютере. Альтернативное поведение есть.

  MSB                                LSB
+----+----+----+----+----+----+----+----+
| a1 |a2.2|a2.1|a2.0|a3.1|a3.0|a4.1|a4.0|
+----+----+----+----+----+----+----+----+
| 0  | 0  | 1  | 0  | 0  | 1  | 1  | 0  |
+----+----+----+----+----+----+----+----+
|        0x2        |        0x6        |
+----+----+----+----+----+----+----+----+

Это было очевидно поведение, которое вы ожидали.

Поскольку это определяется реализацией, вы можете посмотреть в руководстве и узнать, что делает ваш компилятор, потому что компилятор должен задокументировать его поведение.

Если у вас есть проблемы с переносимостью, вам нужно подумать о том, как вы организуете свои определения структуры так, чтобы они работали так, как вам нужно для работы на каждой используемой платформе.

 jlanza13 апр. 2012 г., 07:46
Ваш ответ действительно полный ... спасибо большое !!!
 12 апр. 2012 г., 20:31
обратите внимание, что для этого конкретного моментаgcc Например, ссылается на ABI:"order of allocation of bit-fields within a unit (C90 6.5.2.1, C99 6.7.2.1): Determined by ABI" gcc.gnu.org/onlinedocs/gcc/…
Решение Вопроса

бит в единице.

(C99, 6.7.2.1p10) "The order of allocation of bit-fields within a unit (high-order to low-order or low-order to high-order) is implementation-defined."

В вашей реализации биты сначала сохраняются в единицах lsb (младший значащий бит), а не в msb (младший значащий бит), как вы ожидаете.

Что у вас есть:

[a1.0] [a2.0] [a2.1] [a2.2] [a2.0] [a3.1] [a4.0] [a4.1] 
   0      0      1      0      1      0      0      1
 bit 0                     -                      bit 7

 lsb                       -                      msb

который0x94 если вы считаете, что самый левый бит является наименее значимым битом.

 12 апр. 2012 г., 20:41
@jlanza исправлено, от lsb до msb0 010 10 01 и не0 010 01 10.
 12 апр. 2012 г., 18:50
Мне нравится мой комментарий лучше, чем ваш ответ - даже если ваш правильный :)
 12 апр. 2012 г., 18:58
@KevinDTimm, если вы считаете, что ваш комментарий лучше, сделайте его ответом
 12 апр. 2012 г., 19:00
причина, по которой я так говорю, заключается в том, что я хотел, чтобы он сам все понял, но мне тоже нравится ваш ответ, потому что ответ обычно не очевиден для людей, использующих битовые поля, и вы хорошо провели его через процесс - слава и amp; upvote (также, мой комментарий не был достаточно большим, чтобы быть ответом - недостаточно информации)
 jlanza12 апр. 2012 г., 19:03
Большое спасибо ... Я думал о LE и BigE. Я работал с такими структурами в течение длительного времени, и это происходит впервые. Почему это 0x94 вместо 0x64? 0110 0100 это 0x64

Ваш ответ на вопрос