#pragma twice

KAB-studio > プログラミング > #pragma twice > 106 Version 6.06 プリプロセッサ色々

#pragma twice 106 Version 6.06 プリプロセッサ色々

前のページへ 表紙・目次へ 次のページへ

 Version 6.06
プリプロセッサ色々

前回は #define の使い方を中心にマクロとかの解説をしてきました
よーするにプリプロセッサは使うな! ってことよね
僕的にはね。でも、実際にはもういろんな所で使われてるから。今回はそ
ういう使用例を見つつ、色々なプリプロセッサについて解説します
ほい
まず、 #define の有効範囲について。たとえばこんな例

void HasDefine()
{
    #define DEF_FLAG_OK 1
}

void UseDefine()
{
    TRACE( "%d\n", DEF_FLAG_OK );
}

両方関数だね。上の関数の中で #define で定数作ってて、下の関数の中
でその DEF_FLAG_OK を使ってる……って、それってできるの?
できるんです。もし #define じゃなく const int を使ってたらこれはで
きないんだけど、 #define は
ただの置き換え! つまり #define は変数じゃないからそーゆーの関係
ないんだ
そういうこと。これが問題になる場合があるんだよね
どういうとき?
たとえば API の Windef.h に max っていうマクロがあります

#define max(a,b)            (((a) > (b)) ? (a) : (b))

右っかわよくわかんない……
これは今回はパス。で、 max っていうのはすごくよくある単語だから、
このマクロの存在がまずいことになることがあるんです
っつーことは、普通にプログラムで max って単語は使えないんだ
そういうこと。しかも、 #define は関数とかネームスペースとか全然関
係ないから
上のみたいに、他の関数に土足で踏み込んじゃうとかあるんだねー
そこで、この #define を解除するプリプロセッサを紹介します。それは 
#undef 

void HasDefine()
{
    #define DEF_FLAG_OK 1
    #undef DEF_FLAG_OK  // 解除!
}

void UseDefine()
{
    TRACE( "%d\n", DEF_FLAG_OK );
    // error C2065: 'DEF_FLAG_OK' : 定義されていない識別子です。
}

おお、 DEF_FLAG_OK が見つかってない!
この #undef を使うと、 #define したものを無効にすることができるん
です
これでさっきの max とか無効にできるんだね
さて、この #undef 以上に使われるのが、 #if 系のプリプロセッサ
 #if 系、ってことはいっぱいあるんだ。普通の if と違うの?
ううん、基本的には同じ。ゼロ以外か、ゼロか、で分岐されるものはね。
とりあえず例を見て

#if 1
    TRACE( "IF_FLAG : Non 0 \n" );
#endif

 #if は、すぐ右側がゼロ以外ならすぐ下から #endif までを残して、ゼ
ロだとその部分を削除します

このままの例だと、 #if の右がゼロ以外だから、上の3行は

    TRACE( "IF_FLAG : Non 0 \n" );

ってなります
 #if と #endif の間の行が残るって事ね
もし #if 0 って書いてあったら、上の3行は

 

つまり空白になります
つまり、プログラムができたりできなかったり、ってなるんだ。 #endif 
は } 代わりね
そう。 { はないけどね
ないけど、インデントするのは見やすいから?
一応ね。しない人もいるし、場合によって異なるから、これは難しいか
も。次回紹介する例でも紹介するから
ふーん。質問! 1 とか 0 とか書いてるけど、直接書いてたら #if の意
味ないじゃん。コンパイルの前だから、変数とかとも関係ないし
同じ、コンパイルの前に数字作れるのあるでしょ
ってことは、 #define ?
そゆこと。 stdafx.h にこういうのがあるでしょ

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

この _MSC_VER を MSDN で見てみて
ほいF1。【組み込みマクロ】って出た
組み込みマクロは、初めっから #define されてる値のこと。こういう値
を使えば
 #if で分岐できるわけだ
 #pragma once は次回に取っといて、次に #else について

#if 1
    TRACE( "IF_FLAG : Non 0 \n" );
#else
    TRACE( "IF_FLAG : 0 \n" );
#endif

普通に else と同じって考えれば、 #if がゼロ以外なら

    TRACE( "IF_FLAG : Non 0 \n" );

で、ゼロなら

    TRACE( "IF_FLAG : 0 \n" );

そういうこと。もうひとつ #elif について紹介します。これは else if
にあたるもの

#define DEF_FLAG 15

#if DEF_FLAG < 10
    TRACE( "DEF_FLAG : - 10 \n" );
#elif DEF_FLAG < 20
    TRACE( "DEF_FLAG : 10 - 20 \n" );
#else
    TRACE( "DEF_FLAG : 20 - \n" );
#endif

 #elif って妙な感じ。ま、 if 系とほとんど同じだから分かりやすいけ
どね
そうだね、ほとんど変わらないと思うよ
あ、あと #if - #endif の中に #if - #endif を入れる事ってできる?
もちろんできるよ。 #if と #endif の間には特に制限はないから
ほうほう、だいたい普通の if と同じね
さて、ここからちょっと重要。実際には、 #if は使わないか、他と組み
合わせて使うことが多かったりします。その組み合わせる時に使うのは、 
defined というもの

#define DEF_FLAG

#if defined DEF_FLAG
    TRACE( "DEF_FLAG : Defined \n" );
#else
    TRACE( "DEF_FLAG : Not Defined \n" );
#endif

 #if のすぐ右にあるね
この #if defined は、すぐ右の単語が #define されていればゼロ以外
、されてなかったらゼロと同じように振る舞います
ってことは、最初の #define DEF_FLAG をコメントアウトしたら、下の
方だけってことになるんだ
そゆこと。ちなみに DEF_FLAG が何に #define されてようが関係ないか

そりゃそーね、この例だと空白になってるんだもん
あと〈定義されてない場合〉を使うことも多かったりします

#if !defined DEF_FLAG
    TRACE( "DEF_FLAG : Not Defined \n" );
#else
    TRACE( "DEF_FLAG : Defined \n" );
#endif

 ! は逆になるんだよね
そう、 if の時に使った ! と同じ意味で、この例だと〈 DEF_FLAG が 
#define されていなかったら〉って条件になります
ちょっとややこしいかな
さらに、 #if defined と #if !defined はよく使われるんで、それぞれ
#ifdef と #ifndef っていうプリプロセッサが用意されてます
おお!
使い方はほとんど同じ。まず #ifdef 

#define DEF_FLAG

#ifdef DEF_FLAG
    TRACE( "DEF_FLAG : Defined \n" );
#else
    TRACE( "DEF_FLAG : Not Defined \n" );
#endif

これはさっきの #if defined と同じね
もひとつ #ifndef 

#define DEF_FLAG

#ifndef DEF_FLAG
    TRACE( "DEF_FLAG : Not Defined \n" );
#else
    TRACE( "DEF_FLAG : Defined \n" );
#endif

これは #if !defined と同じね
で、 #if defined 系と #ifdef 系、どっちを使うかだけど、基本的には
どっちでもいいです
そりゃそうよね、機能同じなんだし
ただ僕的には #if defined 派かな
お、出た水希ちゃん流。その理由は?
 #ifdef と #ifndef は n ひとつしか違わないから分かりにくくて。 
#if defined と #if !defined の違う点、 ! の有無は色違いで気付きやす
いから
記号だもんね
だから僕は #if defined を勧めます

/*
    Preview Next Story!
*/
こんなんでプログラムが変わるんだね〜
ちょっと楽しい?
少し、ね
じゃ、来週はその楽しい気持ちをそぎ落としましょう
げげ
というわけで次回
< Version 6.07 条件コンパイルの世界 >
につづく!
火美ちゃんもプリプロセッサ嫌いになれ〜
イヤ〜!
 
del.icio.us 登録する
Yahoo!ブックマーク 詳細を表示 users
livedoorクリップ 詳細を表示 livedoorクリップ ブックマーク数
はてなブックマーク 詳細を表示 はてなブックマーク ブックマーク数
RSSに登録
del.icio.us 登録する
Yahoo!ブックマーク 詳細を表示 users
livedoorクリップ 詳細を表示 livedoorクリップ ブックマーク数
はてなブックマーク 詳細を表示 はてなブックマーク ブックマーク数
 
このページは、Visual C++ 6.0を用いた C++ 言語プログラミングの解説を行う#pragma twiceの一コンテンツです。
詳しい説明は#pragma twiceのトップページをご覧ください。