![見出し画像](https://assets.st-note.com/production/uploads/images/89001001/rectangle_large_type_2_2956eb65a5becdf55843384b1770e54a.png?width=1200)
【C言語】コンパイラが何をしているのか、ちょっとのぞいてみよう その2 プリプロセッサ
C言語のコンパイラというのは、次の4つのステップで成り立ちます。
(1)プリプロセッサ
(2)コンパイル
(3)アセンブル
(4)リンク
まとめて説明しようと思いましたが、長くなったので個別に。
まずは、プリプロセッサから。
(1)プリプロセッサ
プリプロセッサというのは、「#」で始まるプリプロセッサ命令を処理します。
「#include」で指定されたファイルを読み込み、
「#define」で指定されたマクロを展開し、
「#ifdef」の条件に合致しないコードを除去します。
プリプロセッサが出力するものはまだC言語です。
プリプロセッサの出力をファイルに保存することもできます。
例えば次のようなサンプルコードを考えてみましょう。
'#include "mem.h"
'#define TEST_DATA_LEN 10
void func();
void test_mem_cpy();
int main()
{
func();
return 0;
}
void func()
{
test_mem_cpy();
}
void test_mem_cpy()
{
char data1[TEST_DATA_LEN] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
char data2[TEST_DATA_LEN] = {};
'#ifdef _DEBUG
print_array("data1 ", data1, sizeof(data1));
print_array("data2 ", data2, sizeof(data2));
'#endif
mem_cpy(data2, data1, sizeof(data2));
'#ifdef _DEBUG
print_array("data1 ", data1, sizeof(data1));
print_array("data2 ", data2, sizeof(data2));
'#endif
}
いろいろややこしかったので「#」の前に「'」を付与しています。
これをプリプロセッサだけ通してみます。
cc main.c -E -o _main.c
(“-E”は、「プリプロセッサだけを実行する」というオプションです。プリプロセッサで悩んだときは、これで一目瞭然です。)
するとこうなります。
# 1 "main.c"
# 1 "<built-in>" 1
# 1 "<built-in>" 3
# 385 "<built-in>" 3
# 1 "<command line>" 1
# 1 "<built-in>" 2
# 1 "main.c" 2
# 1 "./mem.h" 1
void mem_cpy(
char* dp,
char* sp,
int size
);
# 2 "main.c" 2
void func();
void test_mem_cpy();
int main()
{
func();
return 0;
}
void func()
{
test_mem_cpy();
}
void test_mem_cpy()
{
char data1[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
char data2[10] = {};
mem_cpy(data2, data1, sizeof(data2));
}
絵にしてみました。
![](https://assets.st-note.com/img/1665757057507-f9pJveKBfH.png?width=1200)
続きはこちら。
骨休めにこちらもどうぞ。