【问题标题】:Overflow during constant folding on a 16-bit target architecture在 16 位目标架构上不断折叠期间溢出
【发布时间】:2016-09-24 23:16:33
【问题描述】:

我在 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 在常量折叠期间处理较大的中间值吗?

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

是否有我应该了解的最佳实践?

【问题讨论】:

  • 你知道这个编译器是谁提供的吗?您是否尝试过向他们寻求解决方案?
  • 编译器运行正常。我希望找到一种方法让它以不正确但稍微方便的方式运行。

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


【解决方案1】:

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

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

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

这将给出相同的结果,但避免了溢出的大中间值。

【讨论】:

    【解决方案2】:

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

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

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

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

    是否有我应该了解的最佳实践?

    这是一个主观问题。 (我认为您已经使用了最佳方式来进行强制转换。由于它在编译时进行了优化,因此您没有执行成本过高)。

    【讨论】:

      猜你喜欢
      • 2019-08-20
      • 2020-06-03
      • 2021-11-18
      • 1970-01-01
      • 1970-01-01
      • 2015-11-25
      • 2019-09-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多