如何强制GCC编译器在编译时计算常量值?

时间:2015-08-12 09:37:30

标签: gcc compilation macros constants avr

我有以下代码(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在这种情况下我可以确定它们是真正的文字),以使代码更灵活和可读。我还希望能够在编译器之后检查这些值。

所以问题是:

  1. 是否有可能强制GCC编译器在编译时计算这些常量?

  2. 如何检查此计算值?

3 个答案:

答案 0 :(得分:3)

AVR上的

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