2013-04-24 34 views
5

私はwith-constructに似るマクロを探していました。これは、いくつかの他の目的のために役に立つかもしれない"with with macro" C

with (lock(&x), unlock(&x)) { 
    ... 
} 

: 使い方は次のようになります。

私はこのマクロを思い付いた:

#define __with(_onenter, _onexit, v) \ 
    for (int __with_uniq##v=1; __with_uniq##v > 0;)\ 
     for (_onenter; __with_uniq##v > 0; _onexit) \ 
      while (__with_uniq##v-- > 0) 

#define _with(x, y, z) __with(x, y, z) 
#define with(_onenter, _onexit) _with(_onenter, _onexit, __COUNTER__) 

それがなければならないので、3つのネストされたループがあります

  • おそらく変数_onenterを初期化する(C99のみ、もちろん)

    1. 初期化ループカウンタを(with (int fd=open(..), close(fd))など)
    2. コードブロック内にbreakを許可します。

    私はXV6のOSのコードでそれを使用し、それは非常に有用と思われる(continueも許可されている。そして、マクロがassert()にそれを調整することができます)。

    私の質問です - このようなマクロの最悪の問題は何ですか?つまり、Cマクロ(単なる新しい制御フロー構築を実装したマクロ)の単なる使用に加えて、

    は、これまでのところ、これらの欠点/問題を発見した:

    1. returnまたはgoto(例えばfd < 0など)のエラーの
    2. はサポートされていません(それはカーネルコード内のいくつかgoto Sを保存することができます)のサポートはありません。私はこれが修正可能だと思います。
    3. gnu89/c99以上(ループカウンタ。独自の変数のトリックは必要ありません)
    4. 単純なロックの解除よりも多少効率が悪いです。私はそれが重要ではないと信じています。

    その他の問題はありますか? Cで同様の構文を実装するより良い方法はありますか?

  • 答えて

    6

    そのマクロは私を怖がらせる。私はtraditional approach using gotosが好きです。

    このアプローチは基本的なものですが、ほとんどのCプログラマはこのパターンに精通していますが、そうでない場合はローカルコードを読んで理解することができます。隠された行動はありません。結果として、それはかなり信頼できます。

    あなたのマクロは賢いですが、ほとんどの人には新しく、隠された問題があります。新しい投稿者は、「withブロックの外にreturnまたはgotoを入れないでください」や「breakが周囲のループからではなくwithブロックから壊れてしまう」などの考えられるルールが必要です。私は間違いがよくあることを恐れる。

    この構文の誤用に関する警告をコンパイラに追加することができれば、天びんが移動します。 With clang、これはオプションのようです。この場合、誤使用が検出され、あなたのコードは他のコンパイラに移植可能なままになります。

    GCCとClangに自分自身を限定したい場合は、cleanup属性を使用できます。それはあなたの例では、このように見えるようになります:それはスコープの外に出るとき

    lock_t x = NULL __attribute__((cleanup(unlock))); 
    lock(&x); 
    

    そしてunlock

    は、変数へのポインタで呼び出されます。これは、 returngotoのような他の言語機能と統合されており、C/C++の混在プロジェクトでも例外があります。

    +0

    ああ。最後に応答...ありがとう、私は 'クリーンアップ'について知りませんでした - 有用な音。そのマクロは、その奇妙さの他に、より具体的な問題を持っていますか? – Elazar

    +1

    関数の途中で 'return'ステートメントに対して厳密なコーディング標準で作業しているのでなければ、' return'のサポートが不足しているように見えます。 'with'ブロックの' return'は目立たないように見えますが、実行時に大混乱を招きます。 – pdw

    +0

    私は理解し、 'return'が大きな問題であることに同意します(' cleanup'ははるかに優れています)。しかし、「goto」は厳密な厳密なコーディング基準を必要としないのですか?この点で、gotoの利点は何ですか? – Elazar