【问题标题】:Storing int16_t's in uint64_t's将 int16_t 存储在 uint64_t 中
【发布时间】:2017-10-15 00:05:42
【问题描述】:

所以我有 4 个 uint16_t,我试图将它们存储在一个 uint64_t 中。我想我有这个工作。

uint64_t encode(int16_t A, int16_t B, int16_t C, int16_t D){
    return (uint64_t)((uint16_t) A) << 48
         | (uint64_t)((uint16_t) B) << 32
         | (uint64_t)((uint16_t) C) << 16
         | (uint64_t)((uint16_t) D) <<  0;
}

int main(){

    int16_t A1 = -32000;
    int16_t B1 = -31000;
    int16_t C1 = 16004;
    int16_t D1 = 16007;

    uint16_t A2 = 32000;
    uint16_t B2 = 15000;
    uint16_t C2 = -4;
    uint16_t D2 = -7;

    uint64_t E = encode(A1, B1, C1, D1)
               + encode(A2, B2, C2, D2);

    printf("%d\n", (int16_t)((E >> 48)));
    printf("%d\n", (int16_t)((E >> 32)));
    printf("%d\n", (int16_t)((E >> 16)));
    printf("%d\n", (int16_t)((E >>  0)));
}

我已经能够对 4 个 int16_t 进行编码,然后使用这种方法将它们取回。现在,我想将两个编码形式加在一起,对它们进行解码,然后返回原始操作。我似乎被 1 个错误弄得一团糟。

我这里的输出是 0、-15999、16001、16000。 两个输出正确(0 和 16000),两个输出差一。

我会注意到我曾尝试先将 int16_t 转换为 uint16_t(添加 32768),但没有成功。

【问题讨论】:

    标签: c unsigned signed stdint


    【解决方案1】:

    您正在从一个号码到另一个号码。就像您将十进制数 19 编码为 1923 编码为 23 然后将它们加在一起:19 + 23 = 42,但 1 + 2 = 3。所以最高位是“减一”。

    即使您想避免完全拆包,您仍然可以执行以下操作:

    result = 
      ((a&0xffff0000ffff0000 + b&0xffff0000ffff0000) & 0xffff0000ffff0000) |
       (a&0x0000ffff0000ffff + b&0x0000ffff0000ffff) & 0x0000ffff0000ffff))
    

    ...分两步执行以避免不适当的进位。

    【讨论】:

    • 是的,你是对的。起初我以为我会避免这个进位问题,因为我的数字从未超过 16 位值的真实范围,但现在我发现这是错误的。
    • 是的,这可能是二进制补码因子?例如。 -1 + -1 = 65535 + 65535 = 131070,其中 mod 65536 = 65534,-2 的二进制补码。所以不是一个截断的答案。但计算时有进位。
    猜你喜欢
    • 2019-05-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-25
    • 1970-01-01
    • 2021-10-31
    相关资源
    最近更新 更多