位移掩模仍然无法实现

时间:2012-01-20 04:12:47

标签: c bit-manipulation

有人可以看看这个草率的代码并向我解释为什么它不起作用。我是否正确包装和拆包? (本实验的目的是使用位移和屏蔽来打包日期。例如31/12/99的控制台输入将被“或”在一起然后“取消”,这是我的代码试图做的。谢谢

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

3 个答案:

答案 0 :(得分:3)

您似乎为月份(0xc00)分配的位数太少,而且您执行此操作的方式并不容易确定您的班次是否正确。

我建议以更一致的方式定义你的常量:

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

...现在您可以像这样设置打包值:

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

...并获得如下单个字段:

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

您现在可以简单地更改偏移定义中字段的顺序,以使日期易于排序:

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

答案 1 :(得分:3)

打包日期的代码是错误的。绘制每个步骤的图表,显示每个位将包含的内容,如下所示(其中'D'是用于当天的位,'M'是用于月份的位,'Y'是有点用于年份,'?'是损坏的位,因为它们包含月份和年份):

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

注意:您的面具在二进制文件中看起来像这样:

DAY_MASK   = 000000DDDDD00000
MONTH_MASK = 0000MM0000000000
YEAR_MASK  = YY00YYY00YYYYYYY

不为你做功课;我强烈建议你做同样的事情:用二进制写出所有内容,这样你就可以看到哪些是在做什么。

答案 2 :(得分:0)

那我们从哪里开始呢? 日是最多31,所以你需要log(32)= 5位,但你还不关心这个。 月份最多为12,因此您需要log(16)= 4位 年份最大为99,因此您需要log(128)= 7位

在你的变量中加入日期。 现在转移到左边为月份腾出空间(4位) 把月份放进去 现在向左移动以腾出空间(7位)

现在先解压缩一天。撤消两个班次。 然后让几个月撤消几年的转变。 为了获得好几年,你不需要换挡,只需戴上面具。

由于掩码是数字的最后n位,其中n是您感兴趣的位数,因此掩码为2 ^ n - 1,其中n是天,月,年的位数。