溢出

2016-09-24 166 views
1

我使用一个16位的目标平台上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,虽然我失去了好处水流量:

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

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

我可以强制预处理器为我做不断折叠吗?

我应该知道哪些最佳实践?

+0

你知道谁提供这个编译器吗?你有没有试图要求他们修复? – ddbug

+0

编译器运行正常。我希望找到一种方式,使其行为方式不正确,但稍微方便一些。 – fkoran

回答

0

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

不,你不能这样做。一般C规则总是被应用。含义MIN_UPDATES_PER_REV将被评估为uint16和MAX_RPM到uint8。乘法的结果不适合uint16并且您将获得-Woverflow。

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

预处理器只做宏替换,GCC做常量折叠。如果问题是强迫GCC做不断的折叠,否则你不能不做,即使没有优化标志,GCC也会做不断的折叠。

我应该知道哪些最佳实践?

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

2

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

另一种方式来解决你的直接问题是重新排序的表达式:

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

这将产生相同的结果,但避免了大的中间体,其溢出。