2016-02-22 4 views
2

Я пытаюсь сохранить дату в беззнаковом INT переменного, мне нужно хранить дату таким образом:Хранения данных в переменном с помощью манипулирования бит

  • Бит 11 до 0 за год (от 0 до 4095)
  • Биты 15-12 для месяца (как если бы они были битами от 0 до 3, поэтому я могу хранить значение от 0 до 11)
  • Биты 20-16 для дня (0-31)

Хранение года это не проблема, так как я это делаю:

unsigned int year=0; 
year=year|2016 

Но тогда я понятия не имею, что я должен положить месяц и день. Как я могу поставить число, подобное 10 в битах от 12 до 15, предполагая, что бит 12 имеет значение 1, бит 13 значение 2 и т. Д.

Какую стратегию я должен использовать?

+1

Подробнее о битовых операторах. – Olaf

+0

Сдвиг для выравнивания каждого поля. –

+1

или использовать бит-поле – BLUEPIXY

ответ

3

В C вы можете сдвигать биты в обоих направлениях, используя a >> b или a << b, где a - число сдвига, а b - количество сдвигов. Вставленные биты будут равны 0 с.

В вашем случае, это было бы

unsigned int time=0; 
time |= year; 
time |= month << 12; 
time |= day << 16; 

Чтобы распаковать его, вы просто должны смещаться time в другом направлении и & его к числу разыскиваемых битов:

int year = time & 0b111111111111; 
int month = (time >> 12) & 0b1111; 
int day = (time >> 16) & 0b11111; 

EDIT

Если Вы хотите, чтобы данные, которые можно заказать из наиболее значащего бита и складывали на него

например:

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

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; 

Если вы хотите, чтобы данные, которые можно заказать из наиболее значащего бита и складывали в наименее значащий бит

например:

00000000000111111111111111111111 
      \___________|___|___/ 
        year month day 

Используйте вместо этого

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; 
+0

Это приведет к перегрузке всех бит? в этом случае я не смогу восстановить год или месяц со значения –

+1

Да, вам также нужно рассказать, как распаковать данные. – user3528438

+1

Но в этом случае биты не так, как мне нужно –

0

Как уже упоминалось, вы можете найти битовое легче работать, чем сдвигая и or'ing для выравнивания битов. Битовое поле объявляется как нормальная структура, но позволяет разделять биты между членами структуры. Для вашего года, месяца, дня, вы могли бы использовать что-то похожее на:

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 в надлежащем порядке.