I'm trying to store a date in an unsigned int variable, i need to store the date in this way:
我正在尝试将日期存储在unsigned int变量中,我需要以这种方式存储日期:
- Bits 11 to 0 for the year (from 0 to 4095)
- Bits 15 to 12 for the month (as if they were bits from 0 to 3, so i can store value from 0 to 11)
- Bits 20 to 16 for the day (0-31)
年度比特11到0(从0到4095)
本月的比特为15到12(好像它们是从0到3的位,所以我可以存储从0到11的值)
当天的比特20到16(0-31)
Storing the year it's not a problem, since i do this:
存储年份不是问题,因为我这样做:
unsigned int year=0;
year=year|2016
But then i have no idea i should put the month and the day. How can i put a number like 10 in the bits from 12 to 15 supposing bit 12 have value 1, bit 13 value 2 etc..
但后来我不知道我应该把月份和日期都放进去。如何将12中的数字设置为12到15,假设第12位的值为1,位13的值为2等。
Wich strategy should i use?
我应该使用哪种策略?
2 个解决方案
#1
3
In C, you can shift bits both ways using a >> b
or a << b
where a is the number to shift and b is the number of shifts. The bits inserted will be 0s.
在C中,您可以使用>> b或a b来双向移位位,其中a是要移位的数字,b是移位的数量。插入的位将为0。
In your case, it would be
在你的情况下,它会
unsigned int time=0;
time |= year;
time |= month << 12;
time |= day << 16;
To unpack it, you simply have to shift time
in the other direction and &
it to the number of wanted bits:
要解压缩它,您只需将时间向另一个方向移动,并将其转换为所需的位数:
int year = time & 0b111111111111;
int month = (time >> 12) & 0b1111;
int day = (time >> 16) & 0b11111;
EDIT
If you want the data to be ordered from the most significant bit and stacked to it
如果您希望从最重要的位对数据进行排序并将其堆叠到其中
ex:
11111111111111111111100000000000
\___________|___|___/
year month day
you just need to shift the data accordingly
你只需要相应地移动数据
PACK:
short int_length = sizeof(unsigned int); //usually 32
unsigned int time=0;
time |= year << (int_length - 12);
time |= month << (int_length - 16);
time |= day << (int_length - 21);
UNPACK:
short int_length = sizeof(unsigned int); //usually 32
int year = (time >> (int_length - 12)) & 0b111111111111;
int month = (time >> (int_length - 16)) & 0b1111;
int day = (time >> (int_length - 21)) & 0b11111;
If you want the data to be ordered from the most significant bit and stacked to the least significant bit
如果您希望从最高有效位对数据进行排序并将其堆叠到最低有效位
ex:
00000000000111111111111111111111
\___________|___|___/
year month day
Use instead this
请改用此
PACK:
unsigned int time=0;
time |= year << 9;
time |= month << 5;
time |= day;
UNPACK:
int year = (time >> 9) & 0b111111111111;
int month = (time >> 5) & 0b1111;
int day = time & 0b11111;
#2
0
As others have mentioned, you may find a bitfield easier to work with than shifting and or'ing to align the bits. A bitfield is declared as a normal structure, but allows segregating bits between the members of the structure. For your year, month, day, you could use something similar to:
正如其他人所提到的,您可能会发现比使用移位和/或对齐位更容易使用位域。位域被声明为普通结构,但允许在结构的成员之间隔离位。对于您的年,月,日,您可以使用类似于:
typedef struct { /* bitfield for year, month, day */
unsigned year : 11,
mon : 4,
day : 4;
} datebits;
The datebits
struct segregates the first 11 bits for the year, the next 4 for the month, and the final 4 for the day. You use it just like any other struct. Here is a short example:
datebits结构分离了年份的前11位,下一个月份的4位,以及当天的最后4位。您可以像使用任何其他结构一样使用它。这是一个简短的例子:
#include <stdio.h>
typedef struct { /* bitfield for year, month, day */
unsigned year : 11,
mon : 4,
day : 4;
} datebits;
typedef union { /* union to avoid violating strict aliasing */
datebits d; /* when shifting datebits to print binary bits */
unsigned u; /* (this is only for putchar bit output) */
} duu;
int main (void) {
unsigned i = 19;
datebits d; /* declare bitfield */
duu du;
d.year = 1999; /* fill bitfield */
d.mon = 12;
d.day = 2;
du.d = d;
printf ("\n year : %u month : %u day : %u\n\n (bits in memory) d : ",
d.year, d.mon, d.day);
while (i--) /* verification of each bit in memory */
putchar ((du.u >> i) & 1 ? '1' : '0');
putchar ('\n');
return 0;
}
Output
$ ./bin/bitfield_datebits
year : 1999 month : 12 day : 2
(bits in memory) d : 0010110011111001111
(note: the union is just to facilitate the binary printing of the individual bits, it is not needed for normal use of datebits
).
(注意:联合只是为了方便二进制打印各个位,正常使用datebits不需要它)。
As you can see your day is 0010
, your month 1100
and the year 11111001111
in proper order.
正如您所看到的那样,您的一天是0010,您的月份是1100,年份是11111001111。
#1
3
In C, you can shift bits both ways using a >> b
or a << b
where a is the number to shift and b is the number of shifts. The bits inserted will be 0s.
在C中,您可以使用>> b或a b来双向移位位,其中a是要移位的数字,b是移位的数量。插入的位将为0。
In your case, it would be
在你的情况下,它会
unsigned int time=0;
time |= year;
time |= month << 12;
time |= day << 16;
To unpack it, you simply have to shift time
in the other direction and &
it to the number of wanted bits:
要解压缩它,您只需将时间向另一个方向移动,并将其转换为所需的位数:
int year = time & 0b111111111111;
int month = (time >> 12) & 0b1111;
int day = (time >> 16) & 0b11111;
EDIT
If you want the data to be ordered from the most significant bit and stacked to it
如果您希望从最重要的位对数据进行排序并将其堆叠到其中
ex:
11111111111111111111100000000000
\___________|___|___/
year month day
you just need to shift the data accordingly
你只需要相应地移动数据
PACK:
short int_length = sizeof(unsigned int); //usually 32
unsigned int time=0;
time |= year << (int_length - 12);
time |= month << (int_length - 16);
time |= day << (int_length - 21);
UNPACK:
short int_length = sizeof(unsigned int); //usually 32
int year = (time >> (int_length - 12)) & 0b111111111111;
int month = (time >> (int_length - 16)) & 0b1111;
int day = (time >> (int_length - 21)) & 0b11111;
If you want the data to be ordered from the most significant bit and stacked to the least significant bit
如果您希望从最高有效位对数据进行排序并将其堆叠到最低有效位
ex:
00000000000111111111111111111111
\___________|___|___/
year month day
Use instead this
请改用此
PACK:
unsigned int time=0;
time |= year << 9;
time |= month << 5;
time |= day;
UNPACK:
int year = (time >> 9) & 0b111111111111;
int month = (time >> 5) & 0b1111;
int day = time & 0b11111;
#2
0
As others have mentioned, you may find a bitfield easier to work with than shifting and or'ing to align the bits. A bitfield is declared as a normal structure, but allows segregating bits between the members of the structure. For your year, month, day, you could use something similar to:
正如其他人所提到的,您可能会发现比使用移位和/或对齐位更容易使用位域。位域被声明为普通结构,但允许在结构的成员之间隔离位。对于您的年,月,日,您可以使用类似于:
typedef struct { /* bitfield for year, month, day */
unsigned year : 11,
mon : 4,
day : 4;
} datebits;
The datebits
struct segregates the first 11 bits for the year, the next 4 for the month, and the final 4 for the day. You use it just like any other struct. Here is a short example:
datebits结构分离了年份的前11位,下一个月份的4位,以及当天的最后4位。您可以像使用任何其他结构一样使用它。这是一个简短的例子:
#include <stdio.h>
typedef struct { /* bitfield for year, month, day */
unsigned year : 11,
mon : 4,
day : 4;
} datebits;
typedef union { /* union to avoid violating strict aliasing */
datebits d; /* when shifting datebits to print binary bits */
unsigned u; /* (this is only for putchar bit output) */
} duu;
int main (void) {
unsigned i = 19;
datebits d; /* declare bitfield */
duu du;
d.year = 1999; /* fill bitfield */
d.mon = 12;
d.day = 2;
du.d = d;
printf ("\n year : %u month : %u day : %u\n\n (bits in memory) d : ",
d.year, d.mon, d.day);
while (i--) /* verification of each bit in memory */
putchar ((du.u >> i) & 1 ? '1' : '0');
putchar ('\n');
return 0;
}
Output
$ ./bin/bitfield_datebits
year : 1999 month : 12 day : 2
(bits in memory) d : 0010110011111001111
(note: the union is just to facilitate the binary printing of the individual bits, it is not needed for normal use of datebits
).
(注意:联合只是为了方便二进制打印各个位,正常使用datebits不需要它)。
As you can see your day is 0010
, your month 1100
and the year 11111001111
in proper order.
正如您所看到的那样,您的一天是0010,您的月份是1100,年份是11111001111。