2015-12-15 13 views
6

イム読み取りに関するヘルプが必要な場合、私はこのような定義C++コードのマクロ定義

#define USE_VAL(X) if (&X-1) {} 

は誰のアイデアを持って発見した、それは何を意味するのでしょうか?

+1

未使用のパラメータの警告を取り除くためにこれを使用していますか? – LogicStuff

+0

'if' - 作者はおそらくこれをやろうとしていました:http://stackoverflow.com/questions/154136/do-while-and-if-else-statements-in-c-c-macroshttp://stackoverflow。com/questions/154136/do-while-else-else-statements-in-cc-macros – LogicStuff

+0

私は存在コードを持っているので、これがどのような目的で使用されているか知りたいのですが、このコードで作業したいです –

答えて

7

名前に基づいて、「未使用変数」警告を取り除く方法のように見えます。

int function(int i) 
{ 
    USE_VAL(i) 
    return 42; 
} 

これがなければ、あなたはパラメータiは、関数内で使用されていないことを警告するコンパイラを得ることができます:意図された使用は、おそらくこのようなものです。

しかし、コードに未定義の振る舞い(実際の配列の境界を越えるポインタ算術は標準では定義されていません)が導入されているので、これについてはかなり危険な方法です。 は、オブジェクトのアドレスに 1を加算することはできますが、1を減算することはできません。もちろん、- 1の代わりに+ 1を使用すると、コンパイラは「条件は常に真」と警告できます。 ifをオプティマイザが完全に削除してもコードは有効ですが、オプティマイザは「未定義の動作は起こりません」を悪用する傾向があります。

operator&は、関係するタイプで過負荷になる可能性があることは言うまでもありませんが、望ましくない副作用を招く可能性があります。

voidにキャストするなどの機能を実装するより良い方法は、あります

#define USE_VAL(X) static_cast<void>(X) 

しかし、私の個人的な好みはこのように、関数定義内のパラメータの名前をコメントアウトすることです。

int function(int /*i*/) 
{ 
    return 42; 
} 

この利点は、実際にパラメータをマクロに渡した後で誤って使用しないようにすることです。

+0

はい、最後のアプローチです。これははるかに簡単ですが、**コンパイラ警告を静かにするために意図的に何もしない**コードを追加することを伴いません。 –

1

通常、「未使用の戻り値」警告を避けるためです。普通の "キャスト・トゥ・ボイド"イディオムが使用されていない関数のパラメータで正常に機能しても、(一般には__attribute__((warn_unused_result))のマークされた関数)の戻り値を無視すると、特に-pedanticgccが厳しいので、 "fake if"戻り値で何かをやっていると思ってコンパイラを騙すのによく使われます。

+0

右辺値のアドレスは取ることができないので、ほとんどの戻り値では実際には機能しません。 – Angew

0

マクロはプリプロセッサディレクティブです。マクロは、使用されている場所であれば、関連するコードに置き換えられます。

USE_VAL(X)の後には、USE_VAL(X)とは何かを説明するスペースがあります。

まず、xのアドレスをとり、1を引きます。 0の場合は何もしないでください。 USE_VAL(X)は、それがあれば(& X-1)に置き換えられます使用されます

{}

+0

マクロは機能ではありません。 – LogicStuff

+0

はいマクロは機能しません。あなたはこのコンセプトを使って考えることができます。 –

+0

@ KashifArifいいえ、いいえ、**いいえ**。マクロを関数と見なさないでください。彼らは遠く離れていません*マクロは純粋に構文上の置き換えです。関数についてのようなマクロを考えると、あらゆる種類のバグや誤解が起こります。 – Angew

関連する問題