Кто-нибудь может объяснить вывод, как значение хранится и рассчитывается?
#include<stdio.h>
struct bitfield
{
unsigned f1:1;
unsigned f2:2;
unsigned :3;
unsigned f4:4;
unsigned f5:5;
unsigned f6:6;
unsigned f7:1;
unsigned f8:8;
} bf;
main()
{
bf.f1 = 1;
bf.f2 = 0x3;
bf.f4 = 0xff;
bf.f5 = -4;
bf.f6 = 0377;
printf("%d %d %d %d %d %d", bf.f1, bf.f2, bf.f4, bf.f5, bf.f6, bf.f8);
}
Выход: 1 3 15 28 63 0
unsigned fx:n; // Only use the least significant n bits.
// Binary Decimal
bf.f1 = 1; // 1 == [0000 0001]:1 == 1 == 1
bf.f2 = 0x3; // 0x3 == [0000 0011]:2 == 11 == 3
bf.f4 = 0xff; // 0xff == [1111 1111]:4 == 1111 == 15
bf.f5 = -4; // -4 == [0xfffffffc]:5 == 11100 == 28
bf.f6 = 0377; // 0377 == [1111 1111]:6 == 111111 == 63
Очень короткое краткое изложение.
Первый, bf
неинициализированная глобальная переменная Это означает, что это закончится в .bss
сегмент, который обычно инициализируется нулем при запуске (хотя вы можете передать -fno-zero-initialized-in-bss
GCC, чтобы остановить это, не уверен насчет MSVC, и, конечно, это зависит от вашего crt0
). Это объясняет ценность f8
, так как ты не написал ему.
f1
1. Вы назначаете 1. Это очевидно. То же самое с f2
(поскольку гекс 3 — это декабрь 3).
f4
потому что поле для f4 имеет ширину всего 4 бита. 0xFF
представляет собой 8-битный шаблон, который представляет собой все единицы, который затем усекается до 4 битов и, следовательно, равен 15 (самое высокое значение, которое может быть представлено 4 битами).
f5
происходит из-за подписанного / неподписанного преобразования. Комплемент 5-битного двоичного представления -4 равен 11100. Если вы интерпретируете это значение как беззнаковое (или, скорее, просто двоичное число -> десятичное преобразование), вы получите 28.
f6
63 из-за восьмеричного преобразования. Любое литеральное число C, начинающееся с нуля, рассматривается как восьмеричное. Восьмеричное число 377 является десятичным 255 (то есть 11111111 в 8 битах), которое затем усекается до 6 бит, оставляя 111111
, Это 63.
Значения хранятся в указанном вами поле. Однако, поскольку в некоторых случаях, например, bf.f4 = 0xff;
, значение не подходит, оно будет терять старшие биты, следовательно, оно печатает 15 (0x0F). Аналогично для -4 хранится в f5
-4 = 0xFFFFFFFC
как 32-разрядное целое число, но при сохранении в виде 5-разрядного целого без знака оно становится 0x1C или 28. Тот же принцип применяется к f6
,
Существует также 3-разрядный «пробел» с использованием неназванного члена между f2
а также f4
,
Внутри компилятор сделает это с помощью операций AND, SHIFT и OR.
Обратите внимание, что мы не можем знать, если f1
это самый высокий или самый низкий бит всего значения, в котором хранятся поля. Это будет зависеть от реализации компилятора — при условии, что это делается одинаково каждый раз.
unsigned f1:1; // 1 bit is allocated.
bf.f1=1; // you are storing 1 works fine.
unsigned f2:2; // 2 bit is allocated.
bf.f2=0x3; // 3 == '11' in binary so 2 bits are enough so when you print 3 is printed.
unsigned :3;
unsigned f4:4; // 4 bit is allocated.
bf.f4=0xff; // ff is represented as 1111 1111 in binary,
// but only 4 bits are allocated so only f which is 1111
// in binary gets stored in this. when you print using %d, 15 is getting printed.unsigned f5:5; // 5 bits are allocated
bf.f5=-4; // -4 in binary for 5 bits is 11100 but you are printing it as %d so it will print 28. and so on...
надеюсь, это поможет.