gcc 通过右移>>和左移〈〈按位运算进行数据编码

aurhwmvo  于 2022-11-13  发布在  其他
关注(0)|答案(2)|浏览(174)

我正在尝试解决一个C语言编程问题,即使用移位操作将日期编码为2个字节,然后解码为日期、月份和年份。虽然我也可以使用按位&|操作,但我只想使用移位操作。
问题在于:即使一切看起来都是正确的,日期和月份的输出对双位移位操作没有影响。年份是可以的,因为只有一个操作。这意味着双位移位操作不知何故没有按要求运行。
我用过unsigned char,所以最后一个符号位肯定不是问题。Showbits函数只是用来显示位。我在Windows 10中使用的是带有VSCode的gcc g++编译器。

//  Date encoding in 2-byte number

#include <stdio.h>
#include <conio.h>

typedef unsigned int uint;

Showbits(int n)
{
    int i, k, mask;

    for (i = 15; i >= 0; i--)
    {
        mask = 1 << i;
        k = n & mask;
        k == 0 ? printf("0") : printf("1");
    }
}

int main()
{

    uint encd_date, date, month, year;

    year = 2022;
    month = 9;
    date = 15;
    encd_date = 512 * (year - 1980) + 32 * month + date;

    printf("\nEncoded date:%u\n", encd_date);
    printf("\nencd_date: ");
    Showbits(encd_date);

    year = (1980 + (encd_date >> 9));
    month = (encd_date << 7);
    month = (month >> 12);
    date = (encd_date << 11);
    date = (date >> 11);

    printf("\ndate: ");
    Showbits(date);

    printf("\nmonth: ");
    Showbits(month);

    printf("\nyear: ");
    Showbits(year);

    printf("\nDecoded date %u month %u year %u", date, month, year);

    return 0;
}
vwkv1x7d

vwkv1x7d1#

我按照Fe2O3的建议更改了适合16位的数据类型,它按预期工作。

#include <stdio.h>
#include <stdint.h>
#include <inttypes.h>

typedef uint16_t uint;

void Showbits(int n)
{
    int i, k, mask;

    for (i = 15; i >= 0; i--)
    {
        mask = 1 << i;
        k = n & mask;
        k == 0 ? printf("0") : printf("1");
    }
}

int main()
{

    uint encd_date, date, month, year;

    year = 2022;
    month = 9;
    date = 15;
    encd_date = 512 * (year - 1980) + 32 * month + date;

    printf("\nEncoded date:%u\n", encd_date);
    printf("\nencd_date: ");
    Showbits(encd_date);

    year = (1980 + (encd_date >> 9));
    month = (encd_date << 7);
    month = (month >> 12);
    date = (encd_date << 11);
    date = (date >> 11);

    printf("\ndate: ");
    Showbits(date);

    printf("\nmonth: ");
    Showbits(month);

    printf("\nyear: ");
    Showbits(year);

    printf("\nDecoded date %u month %u year %u", date, month, year);

    return 0;
}
yxyvkwin

yxyvkwin2#

似乎左移位的执行被拖回到右移位操作中。
一个桥接“修复”是使用一个中间变量,似乎“清除”的问题。这似乎是工作(周围)无论什么原因。

int main() {
    uint16_t y = 2022;
    uint16_t m = 9;
    uint16_t d = 15;
    uint16_t u;

    uint16_t encd_date = (y-1980)*512 + m*32 + d;

                            y = (encd_date >> 9) + 1980;
    u = encd_date <<  7;    m = u >> (7+5);
    u = encd_date << 11;    d = u >> 11;

    printf( "\nDecoded year %d month %d date %d", y, m, d );

    return 0;
}

/* Output
Decoded year 2022 month 9 date 15
*/

EDIT回到这里... OP试图使用<<(与>>)来清除高位。这里有一个替代方案,它不将位左移到遗忘状态。相反,3个小值被放入一个无符号的16位缓冲区,然后使用shift和+/-(实际上类似于位掩码)再次提取。

以及Showbits()的替代版本(用于16位值)

void Showbits( uint16_t n ) {
    uint16_t cpy = n;
    char buf[ 16 ] = { '0' };
    for( int i = sizeof buf; i-- && cpy; cpy >>= 1 )
        buf[ i ] = "01"[ cpy & 1 ];
    printf( "\n%04X = %.16s\n", n, buf );
}

int main() {
    uint16_t yb = 1900; // 7 bit range: 1900-2027

    uint16_t d = 15, m = 9, y = 2022; // 15 Sept 2022

    // Initial values
    printf( "\n:::: == day %02d month %02d year %d (%d+%d)", d, m, y, yb, y-yb );

    // squeeze into 16 bits: 7+4+5 : yyyyyyymmmmddddd
    uint16_t enc = ((y-yb<<4)+m<<5) + d;
    Showbits( enc );

    // output directly
    // demonstrates right to left processing of function call parameters
    // y is assigned before used to calc m and
    // m is assigned before used to calc d
    printf( "\n%04X == day %02d month %02d year %d",
        enc, (enc-(y<<9))-(m<<5), m=(enc-(y<<9))>>5, yb+(y=(enc>>9)) );

    // or, first decompose
    y =  enc >> 9;
    m = (enc - (y << 9)) >> 5;
    d = (enc - (y << 9)) - (m<<5);
    y += yb;

    // output values
    printf( "\n%04X == day %02d month %02d year %d", enc, d, m, y );

    return 0;
}

输出量

:::: == day 15 month 09 year 2022 (1900+122)
F52F = 1111010100101111

F52F == day 15 month 09 year 2022
F52F == day 15 month 09 year 2022

相关问题