

今、`C++`のマクロを自力で展開しようとしています。  
そこで、"#define" を見つけたのですが、このようになっていました。

[code]

    #ifndef  OuHolder_h
    #define  OuHolder_h
    
[/code]

このような"`#define`"は「`OuHolder_h`が定義されている」ということを表すようなのですが、  
これをどう展開すればよいか分かりません。  
どうすればいいでしょうか?


CC BY-SA 3.0
2015-03-31T06:27:52.283
8596
2015-04-05T14:32:00.750
2015-04-01T03:55:48.410
49
8224
question
c++ preprocessor
#define に関して


言い換えるなら `#ifndef` はその定義がまだ定義されていなければ、という意味です。

そのため、定義されていなければ定義する、ということになります。


CC BY-SA 3.0
2015-03-31T06:51:13.593
8598
2015-03-31T06:51:13.593
7926
8596
answer


何をされようとしているのかは分かりませんが、以下は俗にインクルードガードと呼ばれるものです。説明には書かれていませんが、そのファイルの末尾に『endif』も居るはずです。

[code]

    #ifndef  OuHolder_h
    #define  OuHolder_h
    // 省略
    #endif
    
[/code]

まず、『ifdef』と『ifndef』は違いますので、ご注意を...

『ifndef』から『endif』内は『OuHolder_h』が定義されていなかった場合にのみ実行されます。  
なので、2行目の『define』で『OuHolder_h』が定義されると、『ifndef』から『endif』内は実行されません。

これは、同じheader fileを複数ファイルから読んでいる場合に、何度も同じheader fileを読み込まないようにするためのものです。

まずは、簡単なことから理解して徐々にやりたいことを試して行くことをオススメします。


CC BY-SA 3.0
2015-03-31T07:04:46.967
8599
2015-03-31T07:24:26.797
2015-03-31T07:24:26.797
2383
2383
8596
answer


もし、自力展開が目的なのではなく、プリプロセス完了後のソースを見たいというだけなら、コンパイラがそのオプションを持っていることがありますので、それを使うという手があります。  
例えば、VC++ (コマンド名: `cl`) なら `/E` 、`g++` や `clang++` では `-E`
で、プリプロセス結果を出力することができます。


CC BY-SA 3.0
2015-03-31T16:18:49.777
8623
2015-03-31T16:18:49.777
7831
8596
answer


基礎的なところを書くと

[code]

    #ifndef  OuHolder_h  // もしここまででOuHolder_hというものが定義されて「いないなら」#endifまでのソースコードを有効にする.
    #define  OuHolder_h  // OuHolder_hというマクロを定義する。この行以降OuHolder_hと書かれればこのマクロのこと
    
    #endif
    
[/code]

ということとなる。なので

[code]

    #include <iostream>
    
    #define Macro1
    #ifndef Macro1
        // #ifndefの前でMacro1が#defineされているから、ここはプリプロセスもコンパイルもされない.
        #define SUM( x, y ) (x + y)
        void print_hello(){ std::cout << "Hello, World!" << std::endl; }
    #endif
    
    int main(){
        int x = SUM( 1, 2 );  // SUMは定義されていない。コンパイルエラー.
        print_hello();        // print_helloも同様に定義されていｔない。エラー.
    }
    
[/code]

であればコメントの通りコンパイルエラーとなり

[code]

    #include <iostream>
    
    #ifndef Macro2
        // #ifndefの前で#define Macro2が書かれていないから、プリプロセスもコンパイルも行われる.
        #define SUM( x, y ) (x + y)
        void print_hello(){ std::cout << "Hello, World!" << std::endl; }
    #endif
    
    int main(){
        int x = SUM( 1, 2 );  // 通る.
        print_hello();        // これも通る。Hello, World!とコンソールに出力される.
    }
    
[/code]

こちらは通るということになる。

ちなみに`#define
OuHolder_h`という定義以降からは`OuHolder_h`という識別子がソースコードに記述されている個所は全部``に置き換えるような形で展開する。実際には一切の空白も入れないだろうが。


CC BY-SA 3.0
2015-04-05T14:32:00.750
8797
2015-04-05T14:32:00.750
8675
8596
answer