人力検索はてな
モバイル版を表示しています。PC版はこちら
i-mobile

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__(...) {}
が意味を持ってくることはわかるのですが。。。

●質問者: akunaki
●カテゴリ:ビジネス・経営 コンピュータ
✍キーワード:C++ trace void ビルド リリース
○ 状態 :終了
└ 回答数 : 5/5件

▽最新の回答へ

1 ● pyopyopyo
●10ポイント

http://www.kab-studio.biz/Programing/PragmaTwice/Main/118.html

#pragma twice 118

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


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


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


2 ● syuzabu
●200ポイント

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++)など他のコンパイラではエラーが発生するものもあるようです。


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

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

◎質問者からの返答

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


3 ● obache
●200ポイント

http://www.micfosoft.com/

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の引数に書いた部分が評価されちゃうか否かの違いですね。

◎質問者からの返答

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__

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


4 ● terra5
●200ポイント

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の関数呼び出しでエラーになる例です。

◎質問者からの返答

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


5 ● obache
●200ポイント

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)の実行がされてまずいことになります。

◎質問者からの返答

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

関連質問


●質問をもっと探す●



0.人力検索はてなトップ
8.このページを友達に紹介
9.このページの先頭へ
対応機種一覧
お問い合わせ
ヘルプ/お知らせ
ログイン
無料ユーザー登録
はてなトップ