C/C++のプリプロセッサと#include
- 2014/08/10
- #C++
お久しぶりです.
まず, 7/30〜8/9の間, いろいろあって家族でアメリカに行ってきました.
旅行中の写真はflickrにあげているのでよかったらみてくださひ. 2014_America
さて, C/C++では必要なライブラリ等を読み込むときに#include
というワードを使いますね.
僕もつい最近までは何も気にせずそう書いていたのですが, 今年何度か学校の図書館から借りて読んでいたこの本
この “10章 C++プロプロセッサ” , というかまぁCプリプロセッサの話題を読んでなんてこったいとなったので記事を書くことにしました.
Cプリプロセッサこわい
まず
#include <stdio.h>
int main(void) {
// なんか処理
return 0;
}
これをおまじないと教えられている方はこちらの記事などを先に読んでください.
C言語はこうやって教えてくれればいいなって思っただけ
Cプリプロセッサとは
ソースコードのコンパイル前にソースコードに対して行う処理のことをプリプロセスと呼び, その処理を行うプログラムをプリプロセッサと呼ぶらしいです.
Cのプリプロセッサの命令は#で始まるアレ, #define
とか#ifdef
とか今回の話題である#include
とかそういうやつです.
例えばこんなC++のコード
#include <iostream>
#define START int main() {
#define END }
#define PRINT(x) std::cout << x << std::endl;
START
PRINT("myon")
END
**は???**ってなるかもしれませんが問題なく動きます.
7〜9行目の部分, これは3〜5行目に定義されたプリプロセッサ命令により, コンパイル前に
int main() {
std::cout << "myon" << std::endl;
}
に展開され, その後コンパイルされます.
このようなコンパイル前に行われる “展開” などの処理がプリプロセッサです.
#include
#include
は “外部のヘッダファイル等を利用するときに使う命令” として普段使われていますが, “指定したファイルの内容をソースコードに挿入する命令” と言ったほうが正しい気がします.
例えばCで#include <stdio.h>
しているコードを% gcc -E hoge.c
としてプリプロセッサの展開をすると800行超のコードが生成されますし, C++の#include <iostream>
では18,000行近いコードが生成されます. (環境によって行数は異なります)
これは, 標準ライブラリであるstdio.h
やiostream
のファイルの内容を挿入し, さらにその中のマクロを展開されるためです.
そして, includeするものはヘッダファイルである必要は無いのでこんなこともできてしまいます.
// myon.cc
#include <iostream>
int main() {
int array[] = {
#include "arrayfile"
};
for (auto&& i: array) {
std::cout << i << std::endl;
}
}
// arrayfile
1, 2, 3, 4, 5, 6, 7, 8 ,9, 10
実行するとこんな感じ
% g++ -std=c++11 pp001.cc
% ./a.out
1
2
3
4
5
6
7
8
9
10
まとめ
CプリプロセッサはソースコードをC/C++の文法に関係なく強引にソースコードを置換等行うのであんなことやこんなことができてしまうが, 度を超えたマクロは危険であるうえにデバッグやコードの理解を困難にするので良くない.
C++のモジュール
#include
は先ほど示したようにアレだし, その他多くの問題があるので, C++ではモジュールと呼ばれる機能の提案がされているらしい.
これに関しては詳しい方の記事を参考にしてください.
N4047: A Module System for C++
本の虫: 2014-05-pre-Rapperswil-mailingのレビュー: N4040-N4051
良さそうなので実用化に期待したい.
どうでもいいけど
よくC++ソースの拡張子は.cpp
とされているようですね.
そして, CプリプロセッサはCPPと略されますね.
あれ・・・???
僕はC++ソースの拡張子は.cc
を推します.