在16位目标体系结构上持续折叠时溢出

时间:2016-09-24 23:16:33

标签: gcc c-preprocessor avr avr-gcc constantfolding

我在16位目标平台上使用avr-gcc

我想做这样的事情:

#define F_CPU 16000000
#define MIN_UPDATES_PER_REV 100
#define MAX_RPM 10000
#define UPDATE_PERIOD_cy ( F_CPU*60 / (MIN_UPDATES_PER_REV*MAX_RPM) )

正如预期的那样,我收到溢出错误,因为MIN_UPDATES_PER_REV * MAX_RPM的计算结果为0xf4240:

bldc.h:9:40: warning: integer overflow in expression [-Woverflow]
#define UPDATE_PERIOD_cy ( F_CPU*60 / (MIN_UPDATES_PER_REV*MAX_RPM) )
                                                          ^

如果我将常量强制为32位并在折叠后转换回uint16_t,那么事情就会成功,尽管我失去了-Woverflow的好处:

#define UPDATE_PERIOD_cy (uint16_t)( (uint32_t)F_CPU*60 / ((uint32_t)MIN_UPDATES_PER_REV*MAX_RPM) ))

我可以强制gcc在常量折叠期间处理大的中间值吗?

我可以强制预处理器为我做持续折叠吗?

我应该了解最佳做法吗?

2 个答案:

答案 0 :(得分:2)

您可以通过为其添加后缀来指定常量的大小,例如100UL100LL

解决当前问题的另一种方法是重新排序表达式:

#define UPDATE_PERIOD_cy ( F_CPU*60 / MIN_UPDATES_PER_REV / MAX_RPM) )

这将得到相同的结果,但避免溢出的大中间件。

答案 1 :(得分:0)

  

我可以强制gcc在常量期间处理大的中间值   折叠?

不,你不能这样做。始终应用通用C规则。含义MIN_UPDATES_PER_REV将被评估为uint16,MAX_RPM将评估为uint8。乘法的结果不适合uint16,你得到-Woverflow。

  

我可以强制预处理器为我做持续折叠吗?

预处理器只进行宏替换,GCC进行常量折叠。如果问题是强迫GCC进行常数折叠,那么即使没有优化标志,GCC也不会进行常数折叠。

  

我应该了解最佳做法吗?

这是一个主观问题。 (我认为你已经使用了最好的方法来进行转换。因为它在编译时进行了优化,所以你没有执行过度成本。)