gccには-Wconversion
、より広いタイプからより狭いタイプへの暗黙の変換があり、情報が失われる可能性がある場合に警告を生成する便利なフラグがあります。残念ながら、次のような...役に立たない...動作があります。
このプログラムを検討してください。
int main(void) {
short x = 1;
x = x+x;
return 0;
}
これを-Wconversionでコンパイルすると、
nonsense.c: In function 'main':
nonsense.c:3:8: warning: conversion to 'short int' from 'int' may alter its value [-Wconversion]
これは十分に公平です。ほとんどのプラットフォームでは、これが発生した場合に予期しないことが発生しx==0x8000
ます。(この警告を受け取る実際のメカニズム:オペランド+
は「通常の算術変換」の対象となり、intに拡張されます。したがって、結果もint型になります。次に、に割り当てるx
と、より広い値からの暗黙的な変換になります。より狭いタイプに。)しかし、あなたがこの振る舞いを期待し、意図しているとしましょう。(16ビットプロセッサまたは16ビットシフトレジスタをシミュレートしています。またはx
、このコードで可能な値の範囲を知っていて、オーバーフローすることはありません。)明示的なキャストを挿入することでコンパイラに通知できます。 :
int main(void) {
short x = 1;
x = (short)(x+x);
return 0;
}
そしてそれは文句を言わないでしょう。
ここまでは順調ですね。しかし、問題を引き起こしている割り当てが複合割り当て(、、、+=
など*=
)である場合、コードにはポイントがないため<<=
、私が見る限り、この警告を取り除く方法はありません。明示的なキャストを挿入できます。
これは、たとえば、すべてを所有することはできないことを意味します
- -プロジェクトのトップレベルコンパイラフラグのWconversionは、意図されているすべての実際の間違いをキャッチします。
- 複合代入演算子のコード内の任意のインスタンスが、より短い整数型に適用され
int
ます。 - 警告のないビルド。
悲しいようです。
それで、質問:これを回避する良い方法はありますか?私は次のように見ることができます:
#pragma GCC diagnostic ...
バグがないにもかかわらず警告を引き起こすことがわかっているコードのビットで警告を無効にするために使用します。(欠点:醜い、コンパイラ固有。)- 複合割り当てをより長い単一割り当てに展開し、明示的なキャストを挿入します。(欠点:非常に醜いです。)
- オフにし
-Wconversion
ます。(欠点:この警告は他の場所で役立ちます。) - 警告に我慢しなさい。(欠点:使用と互換性があり
-Werror
ません;いずれの場合も、「警告なし」と「一部の警告」の違いは「一部の警告」との違いよりも見つけやすいため、警告なしでコードをコンパイルすることをお勧めします。 「もう少し警告」。)
これらはすべて不十分なようで、私が見逃している何か賢いものがあるかどうか疑問に思っています。
(注:もちろん、それが実際に真実である場合、私は「いいえ、それだけです」という答えを受け入れます。)
したがって、答えは、これが実際に意図された動作であり、上記の動作よりもはるかに優れている動作を停止する方法がないということのように見えます。(Mark Bは、明示的なキャストと同じように機能する関数を記述できることを確認しまし+=
た。ecatmuroperator+=
は、明示的なキャストを行う関数を使用して新しい型を定義することを提案しました。)
私はマークBの答えを受け入れています。タイトルの質問に対する実際の答えは、単に「はい」です:-)。