C语言 有符号和无符号整数乘法

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/16966636/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 06:36:45  来源:igfitidea点击:

Signed & unsigned integer multiplication

cmathtypesmultiplicationfixed-point

提问by phkahler

In fixed point math I use a lot of 16bit signals and perform multiplication with 32bit intermediate results. For example:

在定点数学中,我使用了很多 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);

Lets say a is a q14 number then c with have the same scaling as b.

假设 a 是一个 q14 数,那么 c 与 b 具有相同的缩放比例。

This is fine and works for unsigned as well as signed arithmetic.

这很好,适用于无符号和有符号算术。

The question is: What happens if I were to mix types? For example if I know the multiplier "a" is always going to range from 0.0 to 1.0, it is tempting to make it an unsigned int q15 to get the extra bit of precision (and change the shift count to 15). However, I never understood what happens if you try to multiply signed and unsigned numbers in C and have avoided it. In ASM I don't recall there being a multiply instruction that would work with mixed types on any architecture, so even if C does the right thing I'm not sure it would generate efficient code.

问题是:如果我要混合类型会发生什么?例如,如果我知道乘数“a”的范围总是从 0.0 到 1.0,则很容易将其设为 unsigned int q15 以获得额外的精度(并将移位计数更改为 15)。但是,我从来不明白如果您尝试在 C 中将有符号数和无符号数相乘并避免它会发生什么。在 ASM 中,我不记得有一个乘法指令可以在任何架构上使用混合类型,所以即使 C 做了正确的事情,我也不确定它会生成有效的代码。

Should I continue my practice of not mixing signed an unsigned types in fixed point code? Or can this work nicely?

我应该继续在定点代码中不混合有符号和无符号类型的做法吗?或者这可以很好地工作吗?

回答by Benjamin Leinweber

This postTalks about what happens when multiplying signed and unsigned integers. Short answer is, as long as they are the same rank (size), a signed is implicitly typecast to unsigned.

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

As long as you understand the typecasting rules (of whatever language you are programming in), or use explicit typecasting, and you also understand the implications of typecasting from signed to unsigned (a negative number will produce what may appear as gibberish when typecasted to a signed value), then there should be no issue mixing signed and unsigned types.

只要您了解类型转换规则(无论您使用何种语言进行编程),或者使用显式类型转换,并且您还了解从有符号到无符号类型转换的含义(负数将产生在类型转换为有符号值),那么混合有符号和无符号类型应该没有问题。

回答by Naum

I had a similar problem. It caused an access violation crash in x64version. The code iterates through a buffer of image scan lines. Getting the next scan line pointer goes as:

我有一个类似的问题。它导致x64版本中的访问冲突崩溃。该代码遍历图像扫描线缓冲区。获取下一条扫描线指针如下:

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

Negative stride means iterating from bottom towards top scan line. The product stride * iRowi.e. signed * unsignedis typecasted to unsigned __int64with value 4294963972which pushes the pNextLineout of program's memory.

负步幅意味着从底部到顶部扫描线迭代。该产品stride * iRowsigned * unsigned是类型强制转换为unsigned __int64与价值4294963972这推动pNextLine了程序的内存。

The same happens with the x32program version, but there is no crash. Maybe because the x32pNextLinepointer just wraps around (but stays within the program's memory).

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