1
gcc 4.7.2
c89

こんにちは、

関数のようなマクロはテキスト置換にすぎません。一部のプログラマーはインライン関数を好むことを知っています。私がやったことに何か問題があるのだろうかと思います。

注意すべき点がいくつかありますが、isdn_channelに対して宣言されていないエラーが発生するため、do ... while(0)または中括弧を使用してラップしていません。

#define ISDN_CHANNEL_GET(channel)                                       \
    module_isdn_channel_t *isdn_channel = NULL;                         \
    isdn_channel = channel->base.imp->isdn_channels[channel->isdn_id];  \
    if(!isdn_channel) {                                                 \
        LOG(CRITICAL, "Failed to get channel data");                    \
        return FALSE;                                                   \
    }  

そして、私のソースコードでは、セミコロンを追加せずに、次のように使用しています。

ISDN_CHANNEL_GET(channel)
isdn_channel->base.sync_answer |= SIP_CONNECTED;

すべて問題なく動作しますが、これらの関数のようなマクロを書き始めたばかりなので、確認したいと思います。

提案をありがとう、

4

4 に答える 4

3

マクロでreturnを使用しないでください。

ご存知のように、そのマクロはプリプロセッサに#defineの後にあるものを置き換えるように指示します。

したがって、uは関数の途中で無意識のうちに戻る可能性があります

于 2013-03-26T11:06:53.190 に答える
3

次のようなことをしなければ問題ありません:if(condition)ISDN_CHANNEL_GET(channel)

この問題を回避するには、マクロをdo ... while(0)でラップします。

于 2013-03-26T11:06:54.513 に答える
2

jbgsとManimehalaiによって言及されたものの後に、ここには他の問題があります:

  • マクロパラメータの複数の評価(ここでは2回使用します)
  • 演算子の優先順位(常にパラメーターを括弧で囲みます)
  • タイピングの欠如(できる限りタイピングを使用してください、コンパイラはあなたの友達です)

最初の2つはキラーであり、引数としてより複雑な式を渡すとすぐに、副作用も含まれる可能性があります。3つ目は、同じ名前のフィールドを持つ構造体へのポインターを渡すときにバイトします。たとえば、それはまったく異なることをします。

あなたの例は、実際inlineには同じ機能を持つ関数を書くのが簡単な例です。コンパイラーは、コードのデバッグを行う場合に非常に役立ちます。コンパイラーに対してではなく、常にコンパイラーを使用して作業してください。

于 2013-03-26T14:26:09.597 に答える
1

この関数のようなマクロを実行するたびにcall、拡張されます-時間は最適化しますが、スペースは最適化しません:-)。コンパイルすると、アプリケーションのサイズが確実に拡大します。

私の最初の法則:「空間を最適化することも、時間を最適化することもできますが、空間と時間の両方を最適化することはできません」

于 2013-03-26T11:05:40.713 に答える