C,C++のTRACEをリリースビルドで無効化する定義(よくTRACE.h等に記述されている内容)について、教えてください。

inline void __DUMMY_TRACE__(...) {}
#define TRACE 1 ? ((void) 0) : __DUMMY_TRACE__
この2行の記述がビルド時に有効になるのですが、
なぜいきなり、
#define TRACE ((void) 0)
と記述しないのでしょうか?
もし、#define TRACE __DUMMY_TRACE__
と言う記述であれば、
inline void __DUMMY_TRACE__(...) {}
が意味を持ってくることはわかるのですが。。。

回答の条件
  • URL必須
  • 1人2回まで
  • 登録:2005/08/10 03:03:37
  • 終了:--

回答(5件)

id:pyopyopyo No.1

pyopyopyo回答回数357ベストアンサー獲得回数882005/08/11 19:38:38

ポイント10pt

ちょっと気になったので.


(void)0 はアドレス0 へのアクセスにはなりません.関数へのポインタでもありません.


(void)0 は,C言語で 何もしない と記述する際の常套手段です.詳細は上記URLをご覧下さい.

id:syuzabu No.2

syuzabu回答回数155ベストアンサー獲得回数22005/08/03 07:02:10

ポイント200pt

http://www.hey-to.net/ML-archive/vcppML/2000/msg01451.html

[vcpp 00038073] (void)0 $B4X?t%]%$%s%?$KIU$$$F(B.

結局は処理系依存の為の記述ではないでしょうか?


TRACE(”Hoge”);

というコード記述があった場合、M$社の定義では

1 ? ((void) 0) : __DUMMY_TRACE__(”Hoge”);

と解釈され、akunakiさんの言われている定義では

((void) 0)(”Hoge”);

となります。VC++では「((void) 0)(”Hoge”);」という記述は通常の

「(void)0」(NULLポインタ関数呼び出し)として解釈されるようですが

BC(BorlandC++)など他のコンパイラではエラーが発生するものもあるようです。


正直僕自身も勉強不足なのであまり分かっておりません。(^-^;)

此方のスレッドでも議論されております、参考までに。

id:akunaki

昔の名残とのことですが、他の情報ソースでも同様なのでしょうか?(ちょっと納得がいかないです。)

2005/08/03 09:21:19
id:obache No.3

obache回答回数31ベストアンサー獲得回数02005/08/03 10:03:18

ポイント200pt

TRACE(my_func(i))

なんて書いたときに、

#define TRACE ((void) 0)

だと、

((void) 0)(my_func(i))

になって my_func(i)が実行されちゃいますが、

inline void __DUMMY_TRACE__(...) {}

#define TRACE 1 ? ((void) 0) : __DUMMY_TRACE__

だと、

1 ? ((void) 0) : __DUMMY_TRACE(my_func(i))

となって、my_func(i)が呼び出されません。

#define TRACE __DUMMY_TRACE__

__DUMMY_TRACE__(my_func(i))

となって同様です。

TRACEの引数に書いた部分が評価されちゃうか否かの違いですね。

id:akunaki

inline void __DUMMY_TRACE__(...) {}

#define TRACE 1 ? ((void) 0) : __DUMMY_TRACE__

だと、

まず、2行目の置き換えで、

1 ? ((void) 0) : __DUMMY_TRACE(my_func(i))

となり、次に1行目の置き換えで

だたの、

{}

になるから、本当に何も無くなるということですね?

そうすると、

inline void __DUMMY_TRACE__(...) {}

#define TRACE __DUMMY_TRACE__

では、だめなのでしょうか?

2005/08/03 10:52:07
id:terra5 No.4

terra5回答回数57ベストアンサー獲得回数02005/08/03 10:52:48

ポイント200pt

http://www.techmatrix.co.jp/products/quality/insure/feature/erro...

Insure++ (C C++対応自動エラー検出ツール) : 検出されるエラー一覧

>#define TRACE ((void) 0)

>と記述しないのでしょうか?

これがどんな環境でも成立するためには、アドレス0での呼び出し結果がどんな環境でも一致している必要があります。

が、特定のアドレスの呼び出しは、環境依存、OS依存になりますから、一般的には使えません。

例えば、仮想記憶を持たないOS,環境では物理アドレス0の呼び出しになり、

これが無効処理などでなく特別な処理になる場合もあり、これが別の意味(TRACE)に固定されてしまうと困ることになります。

特定のOS,環境化でならともかく、一般的には使ってはいけない定義でしょう。


URLはNULLの関数呼び出しでエラーになる例です。

id:akunaki

本当の物理アドレス0へのアクセスもあり得ると言うことですね。ご教授有り難う御座います。

2005/08/05 11:40:40
id:obache No.5

obache回答回数31ベストアンサー獲得回数02005/08/06 00:35:17

ポイント200pt

http://www.gnu.org/

The GNU Operating system - the GNU project - Free Software Foundation - Free as in Freedom - GNU/Linux

マクロとinline関数、プリプロセッサとコンパイラの最適化で混乱があるようです。


>まず、2行目の置き換えで、

>1 ? ((void) 0) : __DUMMY_TRACE(my_func(i))

>となり、

はマクロのプリプロセッサによる展開で、ここまではOKですが、


>次に1行目の置き換えで

>だたの、

>{}

>になるから、本当に何も無くなるということですね?

inline関数はマクロではありませんから、ここは正しくありません。あくまでもcのソース上は関数呼び出しです。

ここで、3項演算子の最初の項が必ず真になることから__DUMMY_TRACE__ を呼び出す方は実行されることがない、つまり引数の処理 myfunc(i)は実行されることがない、ということになります。

コンパイラの最適化によっては、結果の実行ファイルではそのように空になるかもしれませんが、それはまた別の話です。


ですから、

>inline void __DUMMY_TRACE__(...) {}

>#define TRACE __DUMMY_TRACE__

ですと、

TRACE(myfunc(i))

__DUMMY_TRACE__(myfunc(i))

です。

cのソース上はmyfunc(i)の結果を引数に関数を呼び出していることになりますから、__DUMMY_TRACE__の実装の中身が空だろうとどうだろうと関係なくて myfunc(i) は必ず実行されなければなりません。ということで、TRACEを無効にしたはずなのに無用なmyfunc(i)の実行がされてまずいことになります。

id:akunaki

3項演算子の最適化と言うことがよくわかりました。有り難う御座いました。

2005/08/07 15:12:11

コメントはまだありません

この質問への反応(ブックマークコメント)

トラックバック

「あの人に答えてほしい」「この質問はあの人が答えられそう」というときに、回答リクエストを送ってみてましょう。

これ以上回答リクエストを送信することはできません。制限について

絞り込み :
はてなココの「ともだち」を表示します。
回答リクエストを送信したユーザーはいません