#ifdef USE_CCOMMANDという記述 libjpeg　のソースコード


[このサイト](http://libjpeg.sourceforge.net)でダウンロードできる「[libjpeg](https://ja.wikipedia.org/wiki/Libjpeg)」のソースコードを見て、

> cjpegとdjpeg - JPEGと、他の一般的な画像フォーマットとの変換を行う。

と記述されていたので、`cjpeg.c`のソースを見ました。  
すると、1~22行あたりまでは利用の規約などが記載されており、24行目あたりからコードが書かれていると思います。

[code]

    #include "cdjpeg.h"     /* cjpeg / djpegアプリケーションの共通デッキ */
    #include "jversion.h"       /* for version message */
    
    #ifdef USE_CCOMMAND     /* Macintosh用のコマンドラインリーダー */
    # ifdef __MWERKS__
    #  include <SIOUX.h>              /* Metrowerksはこれを必要とします */
    #  include <console.h>      /* ... この */
    # endif
    # ifdef THINK_C
    #  include <console.h>      /* ここでそれを宣言してください */
    # endif
    #endif
    
[/code]

> 質問  
>  1\. `include "cdjpeg.h"` これは、`cdjpeg.h`のファイルを読み込んでという意味ですよね？  
>  2\. `#ifdef USE_CCOMMAND` は使い方を調べたんですが、#ifdef <識別子名> <処理>
> となっていて、<識別子名>が定義済みなら<処理>を実行するというコードですよね？  
>  `USE_CCOMMAND` は、読み込んだファイルで定義されている場合も実行するんですか？  
>  3\. `#include
> "cdjpeg.h"`先の`cdjpeg.h`で`cdjpeg.h`と定義されているんですが、`#define`って、`#define A
> B`という記述でコードのAをすべてBと置き換えて実行しなさいという意味ですよね？今回の場合、Bにあたる部分がないのですが、どういう解釈をすればよいですか？




大前提として、C言語及びC++言語ではソースコードをコンパイラー本体に渡す前にプリプロセッサで前処理します。質問の`#include`、`#ifdef`、`#define`等はプリプロセッサに対するコマンドであり、コンパイラー本体はこれらを参照しません。  
コンパイルオプション`-E`を使用するとプリプロセッサで処理されコンパイラー本体が参照する生のソースコードを得ることができます。参考までにプリプロセッサによってどのような処理が行われているのか確認することをお勧めします。

この点が理解できていると、疑問点も解消しやすいと思います。

>   1. `include "cdjpeg.h"` これは、`cdjpeg.h`のファイルを読み込んでという意味ですよね？
>

「読み込んで」の対象はコンパイラー本体ではなくプリプロセッサであることに注意してください。`#include
"cdjpeg.h"`はプリプロセッサに対して当該行部分に`cdjpeg.h`を読み込み展開することを指示します。コンパイラー本体は展開済みソースコードを参照することになります。

>   2. `#ifdef USE_CCOMMAND` は使い方を調べたんですが、#ifdef <識別子名> <処理>
> となっていて、<識別子名>が定義済みなら<処理>を実行するというコードですよね？  
>  `USE_CCOMMAND` は、読み込んだファイルで定義されている場合も実行するんですか？
>

「実行する」という解釈が理解を妨げています。  
状況によってコンパイラー本体に見せたいコードと見せたくないコードがあります。その際、プリプロセッサでコンパイラー本体に見せる／隠すを制御します。  
`#ifdef
USE_CCOMMAND`行時点で`USE_CCOMMAND`マクロが定義されている場合は`#endif`までのコードを見せます（つまりソースコードをそのまま残します）。逆に`USE_CCOMMAND`マクロが定義されていない場合は`#endif`までのコードを隠します（具体的には空行に置き換えます）。  
コンパイラー本体はプリプロセッサによって編集されたソースコードを参照します。

>   3. `#include
> "cdjpeg.h"`先の`cdjpeg.h`で`cdjpeg.h`と定義されているんですが、`#define`って、`#define A
> B`という記述でコードのAをすべてBと置き換えて実行しなさいという意味ですよね？今回の場合、Bにあたる部分がないのですが、どういう解釈をすればよいですか？
>

前半部分は意味不明です。後半部分も「実行しなさい」ではありません。  
プリプロセッサがソースコード中の`A`と書かれている部分を全て`B`に書き換えます。`B`にあたる部分がない場合はソースコード中の`A`と書かれている部分を全て消します。  
コンパイラー本体は書き換え後のソースコードを参照することになります。

* * *

以上は概念説明です。C言語登場当時は上記説明の通りに動作していましたが、現在はコンパイルの高速化のためコンパイラー本体がプリプロセッサの役割も兼ねていて、独立したプリプロセッサを呼び出さない場合もあります。しかし、それは実装の違いでしかなく、概念としては現在も変わりません。




大前提として、C言語及びC++言語ではソースコードをコンパイラー本体に渡す前にプリプロセッサで前処理します。質問の`#include`、`#ifdef`、`#define`等はプリプロセッサに対するコマンドであり、コンパイラー本体はこれらを参照しません。  
コンパイルオプション`-E`を使用するとプリプロセッサで処理されコンパイラー本体が参照する生のソースコードを得ることができます。参考までにプリプロセッサによってどのような処理が行われているのか確認することをお勧めします。

この点が理解できていると、疑問点も解消しやすいと思います。

>   1. `include "cdjpeg.h"` これは、`cdjpeg.h`のファイルを読み込んでという意味ですよね？
>

「読み込んで」の対象はコンパイラー本体ではなくプリプロセッサであることに注意してください。`#include
"cdjpeg.h"`はプリプロセッサに対して当該行部分に`cdjpeg.h`を読み込み展開することを指示します。コンパイラー本体は展開済みソースコードを参照することになります。

>   2. `#ifdef USE_CCOMMAND` は使い方を調べたんですが、#ifdef <識別子名> <処理>
> となっていて、<識別子名>が定義済みなら<処理>を実行するというコードですよね？  
>  `USE_CCOMMAND` は、読み込んだファイルで定義されている場合も実行するんですか？
>

「実行する」という解釈が理解を妨げています。  
状況によってコンパイラー本体に見せたいコードと見せたくないコードがあります。その際、プリプロセッサでコンパイラー本体に見せる／隠すを制御します。  
`#ifdef
USE_CCOMMAND`行時点で`USE_CCOMMAND`マクロが定義されている場合は`#endif`までのコードを見せます（つまりソースコードをそのまま残します）。逆に`USE_CCOMMAND`マクロが定義されていない場合は`#endif`までのコードを隠します（具体的には空行に置き換えます）。  
コンパイラー本体はプリプロセッサによって編集されたソースコードを参照します。

>   3. `#include
> "cdjpeg.h"`先の`cdjpeg.h`で`cdjpeg.h`と定義されているんですが、`#define`って、`#define A
> B`という記述でコードのAをすべてBと置き換えて実行しなさいという意味ですよね？今回の場合、Bにあたる部分がないのですが、どういう解釈をすればよいですか？
>

前半部分は意味不明です。後半部分も「実行しなさい」ではありません。  
プリプロセッサがソースコード中の`A`と書かれている部分を全て`B`に書き換えます。`B`にあたる部分がない場合はソースコード中の`A`と書かれている部分を全て消します。  
コンパイラー本体は書き換え後のソースコードを参照することになります。

* * *

以上は概念説明です。C言語登場当時は上記説明の通りに動作していましたが、現在はコンパイルの高速化のためコンパイラー本体がプリプロセッサの役割も兼ねていて、独立したプリプロセッサを呼び出さない場合もあります。しかし、それは実装の違いでしかなく、概念としては現在も変わりません。

