我正在试图弄清楚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位乘法的指令而不会损失精度,那就更好了;但精度得到保证。我正确读到了吗?
祝你好运, 克雷格·布洛姆
答案 0 :(得分:5)
促销有保证,但如果signed int
的范围符合unsigned char
的范围,则会对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
的范围)。