C:8x8->整数提升保证 16 位乘法精度?

发布于 2024-08-29 21:18:51 字数 625 浏览 6 评论 0原文

我试图弄清楚 C 标准(C90,尽管我正在研究 Derek Jones 的带注释的 C99 书)是否保证我在将两个无符号 8 位值相乘并存储为 16 位结果时不会丢失精度。示例语句如下:

unsigned char foo;
unsigned int foo_u16 = foo * 10;

我们的 Keil 8051 编译器(目前为 v7.50)将生成一条 MUL AB 指令,该指令将 MSB 存储在 B 寄存器中,将 LSB 存储在累加器中。如果我首先将 foo 转换为 unsigned int:

unsigned int foo_u16 = (unsigned int)foo * 10;

那么编译器会正确地决定我想要一个 unsigned int,并生成对 16x16 位整数乘法例程的昂贵调用。我想毫无疑问地证明这种防御措施是没有必要的。当我阅读 6.3.1.1 中描述的整数提升时,第一行的效果应该是 foo 和 10 被提升为 unsigned int,执行乘法,并将结果存储为 foo_u16 中的 unsigned int。如果编译器知道一条指令可以执行 8x8->16 位乘法而不损失精度,那就更好了;但精度有保证。我读得正确吗?

此致, 克雷格·布洛姆

I'm trying to figure out if the C Standard (C90, though I'm working off Derek Jones' annotated C99 book) guarantees that I will not lose precision multiplying two unsigned 8-bit values and storing to a 16-bit result. An example statement is as follows:

unsigned char foo;
unsigned int foo_u16 = foo * 10;

Our Keil 8051 compiler (v7.50 at present) will generate a MUL AB instruction which stores the MSB in the B register and the LSB in the accumulator. If I cast foo to a unsigned int first:

unsigned int foo_u16 = (unsigned int)foo * 10;

then the compiler correctly decides I want a unsigned int there and generates an expensive call to a 16x16 bit integer multiply routine. I would like to argue beyond reasonable doubt that this defensive measure is not necessary. As I read the integer promotions described in 6.3.1.1, the effect of the first line shall be as if foo and 10 were promoted to unsigned int, the multiplication performed, and the result stored as unsigned int in foo_u16. If the compiler knows an instruction that does 8x8->16 bit multiplications without loss of precision, so much the better; but the precision is guaranteed. Am I reading this correctly?

Best regards,
Craig Blome

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

つ可否回来 2024-09-05 21:18:51

提升是有保证的,但如果 unsigned char 的范围符合 signed int 的范围,则提升为 signed int 类型。因此(假设它适合)从语言的角度来看,您

unsigned int foo_u16 = foo * 10; 

相当于,

unsigned int foo_u16 = (signed) foo * 10; 

而您显然想要的是

unsigned int foo_u16 = (unsigned) foo * 10; 

如果乘法(结果)不适合signed int 范围。

如果您的编译器对它的解释不同,则可能是编译器中的错误(同样,假设 unsigned char 的范围适合 signed int 的范围)。

The promotion is guaranteed, but the promotion is made to signed int type if the range of unsigned char fits into the range of signed int. So (assuming it fits) from the language point of view your

unsigned int foo_u16 = foo * 10; 

is equivalent to

unsigned int foo_u16 = (signed) foo * 10; 

while what you apparently want is

unsigned int foo_u16 = (unsigned) foo * 10; 

The result of the multiplication can be different if it (the result) doesn't fit into the signed int range.

If your compiler interprets it differently, it could be a bug in the compiler (again, under the assumption that range of unsigned char fits into the range of signed int).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文