1

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) )
                                                          ^

-Woverflow の利点は失われますが、定数を 32 ビットに強制し、折り畳み後に uint16_t に戻すとうまくいきます。

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

一定の折り畳み中に gcc に大きな中間値を処理させることはできますか?

プリプロセッサに定数の折りたたみを強制することはできますか?

知っておくべきベスト プラクティスはありますか?

4

2 に答える 2

2

100ULまたは などの接尾辞を定数に追加することで、定数のサイズを指定できます100LL

当面の問題を解決する別の方法は、式の順序を変更することです。

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

これは同じ結果をもたらしますが、オーバーフローする大きな中間を回避します。

于 2016-09-25T23:14:12.207 に答える
0

一定の折り畳み中に gcc に大きな中間値を処理させることはできますか?

いいえ、これはできません。一般的な C ルールが常に適用されます。意味MIN_UPDATES_PER_REVは uint16 とMAX_RPMuint8 に評価されます。乗算の結果は uint16 に収まらず、-Woverflow が得られます。

プリプロセッサに一定の折りたたみを強制することはできますか?

プリプロセッサはマクロ置換のみを行い、GCC は定数の折りたたみを行います。質問がGCCに定数折りたたみを強制することに関するものである場合、GCCは最適化フラグがなくても定数折りたたみを行うことはできません。

知っておくべきベスト プラクティスはありますか?

これは主観的な質問です。(キャストを行うにはすでに最善の方法を使用していると思います。コンパイル時に最適化されるため、実行のオーバーコストはありません)。

于 2016-09-25T08:10:58.577 に答える