C语言 在常数后使用U和UL以进行正确计算的混淆

nbnkbykc  于 2023-01-01  发布在  其他
关注(0)|答案(1)|浏览(285)

我使用此Map函数将0-1023之间的值Map到0-255之间的值
函数mapping_function将16位无符号整数值作为输入,以Map到0-255
函数声明如下

uint16_t mapping_function(uint16_t x)
{
    return (x*255)/1023;
}

问题是,它不是这样工作的。Map的值不正确,并导致意外的结果值(函数返回)
只有当我像下面这样声明它时它才能工作:

uint16_t mapping_function(uint16_t x)
{
        return (x*255UL)/1023;
}

在第一个常量后使用UL“unsigned long”字面值。

将x变量定义为float,如下所示:

uint16_t mapping_function(float x)
{
        return (x*255)/1023;
}

我怀疑这是由于溢出问题发生的,但我不明白为什么?我感谢任何帮助。谢谢:D

vfhzx4xs

vfhzx4xs1#

采用16位int/unsigned时:溢出。
一个一个一个二个一个 * 一个三个一个。
16-位int/unsigned:数学乘积是unsigned,并且具有足够大的x,由于溢出而被截断。
32-位int/unsignedint中的产品,与所有x的预期一致。
是一个一个一个一个一个一个一个
32-位long/unsigned longunsigned long中的产品,与所有x的预期一致。
64-位long/unsigned longunsigned long中的产品,与所有x的预期一致。
与其使用LL可能过宽或没有L,常数也可能过窄,并且由于乘积可能比16位宽,对于int/unsigned可能是16、32、...的所有系统的可移植代码,使用UINTN_C(value)
它形成一个最小宽度常数,并执行至少32位无符号算术乘法。

#include <stdint.h>
...
  return (x*UINT32_C(255))/1023;

我也怀疑OP的Map是不是最好的。
考虑:

return (x*256UL)/1024;
// or 
return x>>2;

相关问题