Bit-shift masks still elude me

Can someone please take a look at this messy code and explain to me why it doesn't work. Am I packing and unpacking things correctly? (The object of this laboratory was to pack the date using bit shifting and masking. For example, console input 31/12/99 will be OR'ed together, and then AND'ed, which is what my code did ..

#include <stdio.h> #include <stdlib.h> #include <string.h> #define DAY_MASK 0x3e0 #define MONTH_MASK 0xc00 #define YEAR_MASK (~0x3180) void hr() { printf("-----------------------------------------------\n"); } void fields() { printf(" Binary\t\tDTG\t\tBase 10\n"); } void prnFields(unsigned int *day, unsigned int *month, unsigned int *year) { printBits(day); printf("\tDay\t\t%u\n", day); printBits(month); printf("\tMonth\t\t%u\n", month); printBits(year); printf("\tYear\t\t%u\n", year); } int main() { unsigned int day; unsigned int month; unsigned int year; unsigned int packed; printf("Enter numeric Day\t:"); scanf("%d", &day); printf("Enter numeric Month\t:"); scanf("%d", &month); printf("Enter two digit Year\t:"); scanf("%d", &year); printf("\n"); hr(); printf("\nPrepacked Date\n"); fields(); hr(); prnFields(day, month, year); hr(); packed = day; packed <<= 9; packed |= month; packed <<= 4; packed |= year; printf("\nPacked Date\n"); fields(); hr(); printBits(packed);printf("\t\t\t%d\n", packed); hr(); printf("\nUnpacked Date\n"); fields(); hr(); printBits((packed & DAY_MASK)); printf("\tDay\t\t%d \n", (packed & DAY_MASK) >> 9); printBits((packed & MONTH_MASK)); printf("\tMonth\t\t%d \n", (packed & MONTH_MASK) >> 5); printBits((packed & YEAR_MASK)); printf("\tYear\t\t%d \n", (packed & YEAR_MASK)); //system("pause"); return(0); } void printBits(unsigned short int value) { unsigned short int mask =1; int i; mask<<=15; for(i=1; i<=16; i++) { putchar( (mask&value)? '1': '0'); if(i%8==0) { putchar(' '); } value<<=1; } } 
+6
source share
3 answers

It seems that you have too few bits assigned for the month (0xc00), and the way you do it is not easy for you to understand if your shifts are correct.

I would suggest defining your constants more precisely as follows:

 #define DAY_BITS 5 #define MONTH_BITS 4 #define YEAR_BITS 7 #define DAY_OFFSET YEAR_BITS #define MONTH_OFFSET ( YEAR_BITS + DAY_BITS ) #define YEAR_OFFSET 0 #define DAY_MASK ~( ~0 << DAY_BITS ) #define MONTH_MASK ~( ~0 << MONTH_BITS ) #define YEAR_MASK ~( ~0 << YEAR_BITS ) 

... now you can set the packed value as follows:

 packed = 0; packed |= ( day & DAY_MASK ) << DAY_OFFSET; packed |= ( month & MONTH_MASK ) << MONTH_OFFSET; packed |= ( year & YEAR_MASK ) << YEAR_OFFSET; 

... and get single fields as follows:

 printf("\tDay\t\t%d \n", ( packed >> DAY_OFFSET ) & DAY_MASK ); printf("\tMonth\t\t%d \n", ( packed >> MONTH_OFFSET ) & MONTH_MASK ); printf("\tYear\t\t%d \n", ( packed >> YEAR_OFFSET ) & YEAR_MASK ); 

Now you can simply reorder the fields in your offset definitions to make date sorting easier:

 #define DAY_OFFSET 0 #define MONTH_OFFSET DAY_BITS #define YEAR_OFFSET ( DAY_BITS + MONTH_BITS ) 
+3
source

The code for packing the date is incorrect. Draw a chart for each step that shows what each bit will contain (for example, “D” is the bit that is used for the day, “M” is the bit that is used during the month, “Y” is a bit that is used during years, and "?" are bits that are damaged, because they contain both a month and a year):

 packed = day; // 0000000000000000000DDDDD packed <<= 9; // 0000000000DDDDD000000000 packed |= month; // 0000000000DDDDD00000MMMM packed << 4; // 000000DDDDD00000MMMM0000 packed |= year; // 000000DDDDD00YYY????YYYY 

Note. Your masks look like binary:

 DAY_MASK = 000000DDDDD00000 MONTH_MASK = 0000MM0000000000 YEAR_MASK = YY00YYY00YYYYYYY 

Without your homework for you; I highly recommend you do the same thing as me: write everything in binary so you can see which bits do what.

+3
source

So where do we start? Day is a maximum of 31, so for this you need a log (32) = 5 bits, but so far you do not care. The months are no more than 12, so you need log (16) = 4 bits for this Year max 99, so you need log (128) = 7 bits for this

Put the day in your variable. Now move left to make room for a month (4 bits); put a month in; now shift left to make room for a year (7 bits)

Now unzip the first days. Cancel both shifts. Then, to get the months cancel only the shift of years. To get years, you do not need to change, just a mask.

Since masks are the last n bits of a number, where n is the number of bits you are interested in, masks are 2 ^ n - 1, where n is the number of bits for days, months, years.

0
source

Source: https://habr.com/ru/post/906452/


All Articles