C中32位数的乘法

时间:2015-03-05 19:49:57

标签: c 64-bit 32-bit multiplication fixed-point

为什么以下代码会产生此错误?

error: left shift count >= width of type [-Werror]

代码:

int32_t a,b;
int64_t apo;
a = 2673;
b = 19;
apo = BIG_MULL(a,b);
printf("\n %ld \n", apo );

找到的宏here

#define WORD_MASK ((1<<16) - 1)
#define LOW_WORD(x)  (x & WORD_MASK)
#define HIGH_WORD(x) ((x & (WORD_MASK<<16)) >> 16)
#define BIG_MULL(a, b) \
((LOW_WORD(a)  * LOW_WORD(b))  <<  0) + \
((LOW_WORD(a)  * HIGH_WORD(b)) << 16) + \
((HIGH_WORD(a) * LOW_WORD(b))  << 16) + \
((HIGH_WORD(a) * HIGH_WORD(b)) << 32)

我试图乘以32位的有符号值。目标机器不支持64位数学运算。

1 个答案:

答案 0 :(得分:4)

假设您尝试在宏中手动将多个两个32位int转换为64位结果,

((HIGH_WORD(a) * HIGH_WORD(b)) << 32

超出int的长度,所以你有错误。

如果你想让它工作,首先将BIG_MULL改为函数,然后:

  1. 强制转换为long long并执行乘法运算。系统中long long通常足够长,只有32位int
  2. 继续使用适当的结构进行模拟。
  3. 第二个有点微妙,但是可行。首先,您需要在unsigned int上操作并拥有

    struct {
        unsigned int low, high;
    } bigmul_result;
    

    并执行你在宏中所做的事情,但转过来

    ((LOW_WORD(a)  * HIGH_WORD(b)) << 16) + \
    ((HIGH_WORD(a) * LOW_WORD(b))  << 16)
    

    (((LOW_WORD(a)  * HIGH_WORD(b)) + (HIGH_WORD(a) * LOW_WORD(b))) << 16)
    

    这样很容易记住检查总和以查看是否设置了第17位。如果是这样,请在high添加1。