35

たまに、C++でno-opステートメントが必要になります。たとえば、assert()デバッグ以外の構成で無効になっているものを実装する場合(この質問も参照してください):

#ifdef _DEBUG
#define assert(x) if( !x ) { \
                     ThrowExcepion(__FILE__, __LINE__);\
                  } else {\
                     //noop here \
                  }
#else
#define assert(x) //noop here
#endif

これまでのところ、正しい方法は(void)0;ノーオペレーションに使用することであるという印象を受けています。

(void)0;

ただし、一部のコンパイラで警告がトリガーされる可能性があると思われます。C4555: expression has no effect; expected expression with side-effectこれは、この特定のケースでは発行されないが、へのキャストがない場合に発行されるVisualC++警告のようなものvoidです。

それは普遍的に持ち運び可能ですか?もっと良い方法はありますか?

4

11 に答える 11

23

最も単純なノーオペレーションは、コードがまったくないことです。

#define noop

次に、ユーザーコードは次のようになります。

if (condition) noop; else do_something();

あなたが言及する代替案もノーオペレーションです:(void)0;しかし、それをマクロ内で使用する場合は;、呼び出し元が追加できるように脇に置いておく必要があります。

#define noop (void)0
if (condition) noop; else do_something();

(もし;マクロの一部だったら、そこに余分なものがあるでしょう;

于 2011-11-02T10:19:44.277 に答える
20

一部のコンパイラで警告が発生する可能性があると思われます

ありそうもないのは、が定義されたときに((void)0)標準assertマクロが拡張されるものだからです。NDEBUGしたがって、警告を発行するコンパイラは、assertを含むコードがリリース用にコンパイルされるたびに警告を発行します。これはユーザーからはバグと見なされると思います。

コンパイラーは、特別な(void)0扱いをしながら、提案に対して警告することで、その問題を回避できると思います。((void)0)ですから、を使用したほうがよいかもしれませんが((void)0)、私はそれを疑っています。

一般に、余分な囲いのある親の有無にかかわらず、何かを無効にするためにキャストすることは、慣用的に「これを無視する」ことを意味します。たとえばvoid、未使用の変数の警告を抑制するために関数パラメーターをにキャストするCコード。したがって、そのスコアでも、ある警告を抑制すると別の警告が表示されるため、警告したコンパイラはあまり人気がありません。

C ++では、標準ヘッダーが相互に含めることが許可されていることに注意してください。したがって、標準ヘッダーを使用ている場合は、それassertによって定義されている可能性があります。そのため、そのアカウントではコードを移植できません。「普遍的に移植可能」と言っている場合は、通常、標準ヘッダーで定義されているマクロを予約済みの識別子として扱う必要があります。定義を解除することもできますが、独自のアサーションに別の名前を使用する方が賢明です。assertこれは単なる例ですが、すべてのC ++実装にはすでにそれがあり、定義していることを実行しないため、「普遍的に移植可能な」方法で定義したいと思う理由がわかりません。ここで行います。

于 2011-11-02T12:35:53.337 に答える
10

どうdo { } while(0)ですか?はい、それはコードを追加しますが、今日のほとんどのコンパイラーはそれを最適化することができると確信しています。

于 2011-11-02T11:07:51.423 に答える
8

; 標準のノーオペレーションと見なされます。コンパイラがそこからコードを生成しない可能性があることに注意してください。

于 2011-11-02T10:18:40.557 に答える
4

私はこれについてのパーティーにかなり遅れていますが、すべての処理がタイマー割り込みサービスルーチン(ISR)で行われるArduinoプロジェクトのloop()にも同じことが必要でした。関数を定義せずにインラインアセンブラコードが機能することがわかりました。

void loop(){
  __asm__("nop\n\t");             // Do nothing.
}
于 2020-01-13T00:55:35.170 に答える
3

ここでの目的、およびマクロをゼロに定義しない理由は、ユーザーにを追加するように要求;することだと思います。その目的のために、ステートメントが合法である場合(void)0(または((void)0)、またはその他のバリエーション)は問題ありません。

この質問を見つけたのは、単純な古いステートメントが違法であるグローバルスコープで同じことを行う必要があったためです。幸い、C++11は代替手段を提供しますstatic_assert(true, "NO OP")。これはどこでも;使用でき、マクロの後にを要求するという私の目的を達成します。(私の場合、マクロはソースファイルを解析するコード生成ツールのタグであるため、コードをC ++としてコンパイルする場合、常にNO-OPになります。)

于 2018-09-04T14:29:12.253 に答える
1

そして何について:

#define NOP() ({(void)0;})

あるいは単に

#define NOP() ({;})
于 2018-04-13T08:14:33.013 に答える
0

AFAIK、それは普遍的にポータブルです。

#define MYDEFINE()

同様に行います。

別のオプションは次のようなものかもしれません:

void noop(...) {}
#define MYDEFINE() noop()

ただし、私は__noop(void)0のような組み込み関数に固執するか使用します

于 2011-11-02T10:21:17.597 に答える
0

私は使用することをお勧めします:

static_cast<void> (0)   
于 2014-11-02T03:11:41.347 に答える
0

このコードは最適化によって省略されません

static void nop_func()  {   }
typedef void (*nop_func_t)();
static nop_func_t nop = &nop_func;

for (...)
{
    nop();
}
于 2015-11-13T16:34:12.600 に答える
-1
    inline void noop( ) {}

自己文書化

于 2015-03-22T18:00:22.770 に答える