有符号和无符号整数的乘法

7
在固定点数学中,我使用了许多16位信号,并使用32位中间结果进行乘法运算。例如:
int16_t a = 16384; //-1.0q14  or 1.0*2^14
int16_t b = -24576; // -1.4q14  or 1.4*2^14
int16_t c; // result will be q14

c = (int16_t)(((int32_t)a * (int32_t)b)>>14);

假设a是一个q14数字,那么c将与b具有相同的缩放比例。这对于无符号和有符号算术都适用。
问题是:如果我混合使用类型会发生什么?例如,如果我知道乘数"a"的范围始终从0.0到1.0,那么让它成为无符号整数q15以获得额外的精度(并将移位计数更改为15)是很诱人的。然而,我从来没有理解过在C中尝试将有符号和无符号数字相乘会发生什么,并且一直避免这样做。在ASM中,我不记得有任何体系结构上可以使用混合类型的乘法指令,因此,即使C做正确的事情,我也不确定它是否会生成高效的代码。
在定点代码中,我应该继续遵循不混合使用有符号和无符号类型的做法吗?或者这样做可以很好地工作?

2
这篇文章将回答你有关于有符号整数和无符号整数相乘时会发生什么的问题。https://dev59.com/QHVD5IYBdhLWcg3wNY1Z 简而言之,只要它们是同一级别(大小),有符号数字就会被隐式地强制转换为无符号数字。 - Benjamin Leinweber
请发布一个答案而不是评论,这样我就可以接受它了;-) - phkahler
由于某种原因,当时我认为我只回答了你问题的一部分,所以我把它留作评论。现在我再看一遍,我不确定我为什么会这样想。谢谢! - Benjamin Leinweber
2个回答

10

这篇文章讨论了在C语言中将有符号整数和无符号整数相乘时会发生什么。简短的回答是,只要它们的类型(大小)相同,有符号整数就会被隐式转换为无符号整数。

只要你理解了类型转换规则(无论你使用的编程语言是什么),或者使用显式类型转换,并且你也理解了从有符号整数到无符号整数的类型转换的影响(一个负数在类型转换为有符号值后可能会产生看似无意义的结果),那么混合使用有符号和无符号类型就不应该有问题。


在我的情况下,混合类型将根据规则导致错误的结果。这正是我担心的。 - phkahler
1
你能否编辑你上面的帖子,将你输入到a和b中的确切值列出来,这些值导致了违反规则的结果? - Benjamin Leinweber

0

我遇到过类似的问题。在x64版本中,它引起了访问冲突崩溃。代码通过图像扫描行缓冲区进行迭代。获取下一个扫描行指针的方法如下:

unsigned char* pImg = ...
int stride = -3324;
unsigned int iRow = 1; // 2, 3, 4, ...
unsigned char* pNextLine = pImg + stride * iRow

负步幅意味着从底部向顶部扫描线迭代。 乘积 stride * iRowsigned * unsigned 被强制转换为值为 4294963972unsigned __int64,这将使 pNextLine 超出程序内存。

x32 程序版本中也会发生同样的情况,但不会崩溃。 可能是因为 x32pNextLine 指针只是环绕(但仍停留在程序内存中)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接