通过位操作将数据存储在变量中

时间:2016-02-22 23:28:42

标签: c bit-manipulation bitwise-operators bit-shift bits

我正在尝试将日期存储在unsigned int变量中,我需要以这种方式存储日期:

  • 年度第11位至第0位(0至4095)
  • 月份的第15到12位(好像它们是从0到3的位,所以我可以存储从0到11的值)
  • 当天的比特20至16(0-31)

存储年份不是问题,因为我这样做:

unsigned int year=0;
year=year|2016

但后来我不知道我应该把这个月和日。如何将12中的数字设置为12到15,假设第12位的值为1,第13位的值为2等。

我应该使用哪种策略?

2 个答案:

答案 0 :(得分:3)

在C中,您可以使用a << bunsigned int time=0; time |= year; time |= month << 12; time |= day << 16; 双向移位位,其中a是要移位的数字,b是移位的数量。插入的位将为0。

在你的情况下,它将是

time

要解压缩,您只需将&向另一个方向移动,int year = time & 0b111111111111; int month = (time >> 12) & 0b1111; int day = (time >> 16) & 0b11111; 将其移至所需位数:

 11111111111111111111100000000000
 \___________|___|___/
      year  month day

修改

如果您希望从最重要的位订购数据并将其堆叠到其中

例如:

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);

你只需要相应地移动数据

<强> PACK:

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;

<强> UNPACK:

 00000000000111111111111111111111
            \___________|___|___/
                  year  month day

如果您希望从最高有效位对数据进行排序并将其堆叠到最低有效位

例如:

unsigned int time=0;
time |= year << 9;
time |= month << 5;
time |= day;

改为使用

<强> PACK:

int year = (time >> 9) & 0b111111111111;
int month = (time >> 5) & 0b1111;
int day = time & 0b11111;

<强> UNPACK:

var data = new FormData(form);

答案 1 :(得分:0)

正如其他人所提到的,您可能会发现位域比移位和/或对齐位更容易。位域被声明为普通结构,但允许在结构的成员之间隔离位。对于,您可以使用类似的内容:

typedef struct {    /* bitfield for year, month, day */
    unsigned    year : 11,
                mon  :  4,
                day  :  4;
} datebits;

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;
}

<强>输出

$ ./bin/bitfield_datebits

 year : 1999  month : 12  day : 2

 (bits in memory) d : 0010110011111001111

注意:联合只是为了方便二进制打印各个位,正常使用datebits时不需要它。)

您可以按照正确的顺序查看当天0010,您的月份1100和年份11111001111