Cマクロでは、(0)を超える(0)while(0)を超えている場合、{…}を好むべきですか?
-
13-09-2019 - |
質問
顧客は最近、私の雇用主のCコードベースの静的分析を実施し、結果を私たちに与えました。便利なパッチの中には、有名な人を変えるための要求がありました do { ... } while(0)
マクロに do { ... } while(0,0)
. 。私は彼らのパッチが何をしているのか理解しています(シーケンス演算子を使用して 戻る 2番目の「0」の値を評価するため、効果は同じです)が、最初のフォームで2番目のフォームを好む理由は明確ではありません。
マクロの2番目の形式を好むべき正当な理由はありますか、それとも顧客の静的分析が過度にペダンティックであるのですか?
解決
さて、私は答えを求めます:
正当な理由はありますか?
いいえ。正当な理由はありません。どちらも常にfalseと評価され、まともなコンパイラはおそらく2番目のコンパイラをアセンブリの最初のコンパイラに変えます。場合によっては無効になる理由がある場合、Cは、その理由が私よりも大きな達人によって発見されるのに十分な長さであった。
あなたのコードがあなたにフクロウの目を作っているのが好きなら、使用してください while(0,0)
. 。それ以外の場合は、Cプログラミングの世界の残りの部分が使用しているものを使用し、顧客の静的分析ツールを伝えてそれを押します。
他のヒント
なぜ彼らが使用することを提案するのかについての推測
do { ... } while(0,0)
以上
do { ... } while(0)
動作の違いはなく、2つの間にランタイムコストの違いはないはずです。
私の推測では、静的分析ツールが while
より単純な場合に定数によって制御されるループは 0,0
使用されている。顧客の提案はおそらく、ツールから誤った肯定的な束を得ることができないようなものです。
たとえば、時々、定数によって制御された条件付きステートメントを持ちたい状況に出くわしますが、コンパイラは定数を評価する条件付き表現について警告に不満を言います。それから私はいくつかのフープを飛び越えて、コンパイラに不平をやめさせるようにしなければなりません(私は偽の警告が好きではないので)。
あなたの顧客の提案は、私がその警告を静めるために使用したフープの1つですが、私の場合はそれが制御していませんでした while
ループ、それは「常に失敗する」主張に対処することでした。時々、私は決して実行されないコードの領域を持っています(おそらくスイッチのデフォルトのケース)。その状況では、私は常に何らかのメッセージで失敗する主張があるかもしれません:
assert( !"We should have never gotten here, dammit...");
しかし、少なくとも1つのコンパイラを使用します。常に誤って評価する式に関する警告を発行します。ただし、次のように変更すると
assert( ("We should have never gotten here, dammit...", 0));
警告は消え、誰もが幸せです。顧客の静的分析ツールでさえもそうだと思います。私は一般的に、その少しのフープがマクロの後ろにジャンプしているのを隠していることに注意してください:
#define ASSERT_FAIL( x) assert( ((x), 0))
ツールベンダーに問題を修正するように指示できるのはいいことかもしれませんが、実際に一定のブール表現によって制御されるループを診断したいという正当なケースがあるかもしれません。ツールベンダーにそのような変更を加えるよう説得したとしても、それは来年かそこらに役立つことはありません。
使用 while(0,0)
Microsoftコンパイラが定数である条件について警告を生成することを防ぎます(警告C4127)。
この警告が有効になっている場合( /w4または /wallで)、この素敵な小さなトリックでケースバイケースでシャットダウンできます(この他のスレッドを参照してください).
編集:Visual Studio 2017 15.3以来、 while(0)
警告を発しなくなります(cf。 一定の条件)。あなたはあなたを取り除くことができます (0,0)
!