連載
» 2013年09月17日 15時30分 UPDATE

目指せ! Cプログラマ(16):プリプロセッサでプログラムの質を向上させよう (1/4)

プログラミング言語Cの強力な機能の1つに、「プリプロセッサ」があります。正しく使えば、間違いが少なくて、意味も伝わりやすいプログラムを、より簡単に書くことができます。プリプロセッサを使いこなして、プログラムの質をぐっと向上させましょう。

[長沼立巳, 小山博史,SSS(G)/ガリレオ]

 プログラミング言語Cの強力な機能の1つに、「プリプロセッサ」があります。あまりにも自由度が高いため、ときに禁断の魔術のように受け止められることがありますが、優秀なプログラマならば必ずプリプロセッサを自在に使いこなしています。正しく使えば、間違いが少なくて、意味も伝わりやすいプログラムを、より簡単に書くことができる上、コンパイラの詳細な動作さえ変更させることもできるからです。プリプロセッサを使いこなして、プログラムの質をぐっと向上させましょう。

プリプロセッサ

 プログラムをCコンパイラに渡すと、Cのキーワードや識別子が解析される前に、前処理(プリプロセッシング、Preprocessing)が行われます。前処理を行うプログラムをプリプロセッサと呼び、これは「CPP(C Preprocessor)」と略されることもあります。

 プリプロセッサは、その名の通り、コンパイラによるソースコードの字句解析や、構文解析、バイナリコード生成などよりも前に実行されます。私達がプログラムをコンパイラに渡すと、プリプロセッサによって前処理が行われ、その結果がコンパイラに渡されてコンパイルされることになります。どのコンパイラもこのような動作になっていますので、特に意識せずともこのような処理が行われます。

 なぜこのような構成になっているのでしょうか。プリプロセッサでは、主に次のような処理が行われます。

  • ソースコード中にヘッダやソースファイルを取り込む
  • ソースコード中に書かれたマクロを置き換える
  • コンパイル対象となるソースとそうでない部分を指定する
  • 処理系ごとの動作を指定する

 詳細は追って説明しますが、プリプロセッサとは、ソースコード自身やコンパイルの過程に対して、ソースコードの中から指示を与えるためのものと考えればよいでしょう。より踏み込んだ表現をするならば、コンパイラに渡すソースコードをコンパイル時に生成し、そしてそのソースコードをどのようにコンパイルするべきか指示できるように用意されているのです。

 プリプロセッサを使いこなすことで、間違いの少ないプログラムを書くことができるようになり、さらには意味が明確で、読み手に伝わりやすいコードを書くことができるようになります。

 なお、プリプロセッサ用の指令(ディレクティブ)は、行頭の「#」に続けて書きます。その前にスペースやタブなどの空白文字があっても構いませんが、それ以外の文字があるとプリプロセッサでは何も処理されません。また、「//」や「/* */」といったコメント中の指令も処理されません。

前処理の結果を確認する

 プリプロセッサの動作を確認するときには、Cコンパイラがプリプロセッサを通した結果が分かると便利です。大抵のコンパイラではプリプロセッサの結果を標準出力やファイルに出力できますので、調べてみるとよいでしょう。ここではPleiadesで使用されているGCC(GNU Compiler Collection)と、Visual C++での方法を説明します。

 GCCでは-Eオプションを付けると、プリプロセッサの結果が標準出力に出力されます。

> gcc -E test.c

 コメントを残す-Cオプションも併せて指定すると結果が読みやすいでしょう。

 Visual C++(コンパイラのコマンドは「cl.exe」)では/Eオプションで同じ結果が得られます。GCCと同じように/Cオプションを付けるとコメントが残ります。また、/Pオプションを使うとファイルへ出力できます。

> cl /E test.c
> cl /P /C test.c

 後者の例では、コメントを残し、ファイル「test.i」へ結果を出力します。


ヘッダ取り込み

 標準ライブラリの機能を使うとき、プログラムの先頭で「#include <stdlib.h>」のように書きます。これはプリプロセッサの機能で、ヘッダを取り込むためのものです。

 プログラムの規模が大きくなると、その一部の機能をある程度の単位でまとめるのがプログラミングの定石です。Cでは、機能を提供する側がその仕様(関数のプロトタイプ宣言やマクロによる定数定義など)をヘッダとしてまとめ、機能を使う側がそれを取り込んで(インクルードして)使用します。マクロによる定数の定義については後で説明します。

 ヘッダの取り込みには2種類の方法があります。

 1つはこれまで使ってきたような方法です。「#include <stdlib.h>」のように書けば、ヘッダ「stdlib.h」で提供されている機能が利用できるようになります。

 もう1つは「#include "header.h"」のように書く方法です。これは指定したファイルの内容をこの位置に取り込みます。

 標準ライブラリで提供されているヘッダを使用する場合は「#include <header.h>」と書き、自作プログラムのヘッダを使用する場合は「#include "header.h"」と書くと、ここでは覚えておきましょう。より詳しい内容については、翻訳単位について理解してからが良いので、今後本連載で説明します。

       1|2|3|4 次のページへ

Copyright© 2017 ITmedia, Inc. All Rights Reserved.

@IT Special

- PR -

TechTargetジャパン

この記事に関連するホワイトペーパー

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。