55

NDEBUGが定義されている場合、内部的に として定義されているglibcの debug printfs を見てきました。同様に、for Visual C++ コンパイラもあります。前者は GCC と VC++ コンパイラの両方で動作しますが、後者は VC++ でのみ動作します。これで、上記の両方のステートメントが操作なしとして扱われ、それぞれのコードが生成されないことがわかりました。しかし、ここで疑問があります。(void) 0__noop

の場合__noop、MSDN は、コンパイラによって提供される組み込み関数であると述べています。〜に来て(void) 0、コンパイラによって何も操作されないと解釈されるのはなぜですか? それはC言語のトリッキーな使用法ですか、それとも標準はそれについて明示的に述べていますか? それとも、それはコンパイラの実装と関係がありますか?

4

5 に答える 5

75

(void)0(+ ;) は有効ですが、「何もしない」C++ 式です。それがすべてです。これは、ターゲット アーキテクチャの命令に変換されませんno-op。言語が完全なステートメントを期待する場合 (たとえば、ジャンプ ラベルのターゲットとして、またはif句の本体内) のプレースホルダーとしての単なる空のステートメントです。

編集:(クリス・ルッツのコメントに基づいて更新)

マクロとして使用する場合は、次のように注意してください。

#define noop ((void)0)

これ(void)により、誤って次のような値として使用されるのを防ぎます

int x = noop;

上記の式の場合、コンパイラは正しく無効な操作としてフラグを立てます。GCC の吐き気error: void value not ignored as it ought to beと VC++ の吠え声'void' illegal with all types

于 2010-02-04T10:43:41.660 に答える
10

副作用のない式は、コンパイラによってノーオペレーションとして扱われる可能性があり、コードを生成する必要はありません (可能性はありますが)。キャストしてからキャストの結果を使用しないことは、コンパイラー (および人間) にとって、副作用がないと簡単に認識されることがあります。

于 2010-02-04T10:44:42.940 に答える
3

あなたはglibではなくglibcについて話していると思います。問題のマクロはマクロです。assert

(デバッグなし)が定義されているglibc<assert.h>では、次のように定義されています。NDEBUGassert

#ifdef NDEBUG
#if defined __cplusplus && __GNUC_PREREQ (2,95)
# define __ASSERT_VOID_CAST static_cast<void>
#else
# define __ASSERT_VOID_CAST (void)
#endif
# define assert(expr)           (__ASSERT_VOID_CAST (0))
#else
/* more code */
#endif

これは基本的にassert(whatever);と同等((void)(0));であり、何もしないことを意味します。

C89 標準 (セクション 4.2) から:

ヘッダーはマクロを<assert.h>定義し、assert別のマクロを参照します。

NDEBUG

によって定義されていません<assert.h>NDEBUGがインクルードされるソース ファイル内のポイントでマクロ名として定義されている場合<assert.h>assertマクロは単純に次のように定義されます。

#define assert(ignore) ((void)0)

(void)0デバッグ印刷マクロを等しいと定義することはあまり意味がないと思います。それがどこで行われているか見せてもらえますか?

于 2010-02-04T10:53:09.067 に答える
1

そうだとしても、なぜそれを void に型キャストするのでしょうか? また、#define dbgprintf (void) 0 の場合、dbgprintf("Hello World!"); のように呼び出すと、-> (void) 0("Hello World!"); - どういう意味ですか?– 伝説2k

マクロはコードを別のものに置き換えるので、#define dbgprint (x を受け入れる) を

ボイド (0)

X の書き換えは行われず、dbgprintf("Helloworld") は (void) 0("Hello world") ではなく (void) 0; に変換されます。- マクロ名 dbgprint が (void) 0 に置き換えられるだけでなく、呼び出し全体 dbgprintf("...")

于 2011-02-12T19:06:28.227 に答える