依赖整数提升是一种不好的编程习惯吗?

Tom*_*omK 7 c c++ type-conversion integer-promotion

我目前正在为嵌入式系统(C 和 C++)编写一些代码,并且在尝试最小化内存使用时,我注意到我使用了很多依赖于整数提升的代码。例如(据我所知,这段代码在 c 和 c++ 中是相同的):

uint8_t brightness = 40;
uint8_t maxval = 255;
uint8_t localoutput = (brightness * maxval) / 100;
Run Code Online (Sandbox Code Playgroud)

因此,即使亮度 * 255 大于 uint8_t 中可以存储的值,如果我是正确的,由于整数提升,这仍然会产生正确的结果。亮度是一个百分比,因此它永远不应该高于 100,因此本地输出永远不应该高于 255。我的问题是是否有任何意外行为(例如亮度 * maxval 大于 255 因此有溢出)或任何显着差异c++ 和 c 之间如何处理这种语法就是这种情况。似乎只是输出正确的答案,或者更建议将变量设为 uint16_t 类型,因为中间计算可能高于 255,并且将内存损失视为理所当然。

chq*_*lie 3

您的问题提出了 C 编程和一般编程中的一个重要问题:程序在所有情况下都按预期运行吗?

该表达式(brightness * maxval) / 100计算的中间值brightness * maxval可能超出用于计算它的类型的范围。在 Python 和其他一些语言中,这不是问题,因为整数没有限制范围,但在 C、C++、java、javascript 和许多其他语言中,整数类型具有固定位数,因此乘法可能会超出此范围。

程序员有责任确定操作数的范围以确保乘法不会溢出。这需要很好地理解整数提升和转换规则,这些规则因一种语言而异,并且在 C 中有些棘手,尤其是混合有符号和无符号类型的操作数。

在您的特定情况下, 和brightnessmaxval类型都小于int因此它们被提升为int具有相同的值,并且乘法产生一个int值。如果是tobrightness范围内的百分比,则结果在to范围内,C 标准保证该值在 type 范围内,并且将此数字除以会产生一个在to范围内、在 范围内和范围内的值在目标类型的范围内,因此操作是完全定义的。0100025500int1000100intuint8_t

此过程是否应该记录在注释中或通过调试断言进行验证是本地编码规则的问题。将操作数的顺序更改为maxval * brightness / 100并可能使用更明确的值和变量名称可能会对读者有所帮助:

uint8_t brightness100 = 40;
uint8_t localoutput = 255 * brightness100 / 100;
Run Code Online (Sandbox Code Playgroud)

这个问题比整数提升问题更普遍,所有此类计算都应该针对极端情况和值范围进行分析。自动化工具可以帮助执行范围分析并优化编译器来改进代码生成,但这是一个难题。