我有以下代码(CPU Atmel AVR ATmega64A):
#define UO_ADC1023 265
#define UREF_180V (1023*180/UO_ADC1023)
....
if(ADC > UREF180) {do_something();}
这应该将UREF_180V
评估为694.87 ...并且该值应该四舍五入(更好)到695或者将(更差)更低到694以与ADC寄存器进行比较。
但是我在编译时发出integer overflow
警告。据此我假设编译器生成的代码在运行时计算(1023*180/UO_ADC1023)
,这在我的情况下非常糟糕。
我想避免自己计算这些常量(#define UREF_180V 695
在这种情况下我可以确定它们是真正的文字),以使代码更灵活和可读。我还希望能够在编译器之后检查这些值。
所以问题是:
是否有可能强制GCC编译器在编译时计算这些常量?
如何检查此计算值?
答案 0 :(得分:3)
int
是16位。告诉编译器使用long
代替(因为1023 * 180会溢出)。
#define UREF_180V (1023L * 180 / UO_ADC1023)
答案 1 :(得分:2)
将宏插入到调用位置,稍后可以编译它们的内容。
在C ++ 11中,您可以使用constexpr
在编译时计算表达式,如下所示:
constexpr auto UREF_180V = 1023*180/UO_ADC1023;
由于所有数字均为int
,因此结果为694
。要正确舍入它,您必须将其中一个值更改为浮点数并创建一个constexpr
舍入函数,该函数可在编译时调用。
至于检查号码,您可以使用static_assert(695 == UREF_180V, "");
。
要编译C ++ 11代码,请将-std=c++11
添加到编译器选项中。 (你可能不得不切换到C ++项目,而且我不完全确定AtmelStudio是否支持C ++ 11,如果不是,我很抱歉)
答案 2 :(得分:2)
请参阅-fmerge-all-constants命令,-fgcse,-fsee或更好,请参见此处:https://gcc.gnu.org/onlinedocs/gcc-4.2.2/gcc/Optimize-Options.html
尽管如此,整数溢出可能是代码中语义错误的一部分,因为提到了welternsturm