我在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在常量折叠期间处理大的中间值吗?
我可以强制预处理器为我做持续折叠吗?
我应该了解最佳做法吗?
答案 0 :(得分:2)
您可以通过为其添加后缀来指定常量的大小,例如100UL
或100LL
。
解决当前问题的另一种方法是重新排序表达式:
#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也不会进行常数折叠。
我应该了解最佳做法吗?
这是一个主观问题。 (我认为你已经使用了最好的方法来进行转换。因为它在编译时进行了优化,所以你没有执行过度成本。)