Манипулирование битовым полем

В следующем коде

#include <iostream>

using namespace std;
struct field
{
unsigned first : 5;
unsigned second : 9;
};
int main()
{
union
{
field word;
int i;
};
i = 0;
cout<<"First is : "<<word.first<<" Second is : "<<word.second<<" I is "<<i<<"\n";
word.first = 2;
cout<<"First is : "<<word.first<<" Second is : "<<word.second<<" I is "<<i<<"\n";
return 0;
}

когда я инициализирую word.first = 2, как и ожидалось, он обновляет 5-битное слово и выдает желаемый результат. Вывод ‘i’ немного сбивает с толку. При word.first = 2 я выдаю вывод как 2, а когда я делаю word.second = 2, вывод для i равен 64. Так как они совместно используют один и тот же блок памяти, не должен быть вывод (для i) в последнем случае 2?

2

Решение

Этот конкретный результат зависит от платформы; ты должен читать дальше порядок байт.

Но чтобы ответить на ваш вопрос, нет, word.first а также word.second не делиться памятью; они занимают отдельные биты. Очевидно, что базовое представление на вашей платформе таково:

bit   15 14 13 12 11 10  9  8  7  6  5  4  3  2  1  0
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|     |         second           |    first     |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|<------------------- i ----------------------->|

Итак, постановка word.second = 2 устанавливает бит № 6 iи 26 = 64

7

Другие решения

Хотя это зависит как от вашей платформы, так и от вашего конкретного компилятора, это то, что происходит в вашем случае:

Объединение накладывает как int, так и struct на одну и ту же память. Предположим сейчас, что ваш int имеет размер 32 бита. Опять же, это зависит от нескольких факторов. Ваше расположение памяти будет выглядеть примерно так:

IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
SSSSSSSSSFFFFF

куда я обозначает целое число, S для второго поля и F для первого поля вашей структуры. Обратите внимание, что я представил самый значимый бит слева.

Когда вы инициализируете целое число в ноль, все биты устанавливаются в ноль, поэтому первый и второй также равны нулю.
Когда вы устанавливаете word.first в два, расположение памяти становится:

00000000000000000000000000000010
IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
SSSSSSSSSFFFFF

Что приводит к значению 2 для целого числа. Однако, установив значение word.second в 2, расположение памяти становится:

00000000000000000000000001000000
IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
SSSSSSSSSFFFFF

Что дает вам значение 64 для целого числа.

1