C言語のあれこれ9(プリプロセッサの利用方法)
はじめに
以下の記事の続きになります。
C言語のあれこれ6(条件に関する演算子と条件分岐、繰り返し文の作成方法)
以下の順番で作成していきます。
- 変数と定数の作成方法
- 基本的な値型の種類と構造体の作成方法
- 関数の作成方法
- 計算するための演算子の説明
- 条件に関する演算子と条件分岐、繰り返し文の作成方法
- 配列を伴わないポインタの使用方法
- 配列を伴ったポインタの使用方法
- プリプロセッサの利用方法 <=今回の記事
追記
C言語のあれこれ8
まででは1ファイル内で基本的な開発ができますが、stdio.h
のようなファイルの説明はされませんでした。
じゃあ'#include<stdio.h>'とは何なのかを説明してC言語の開発方法の説明を終了します。
本編
ここではプリプロセッサの利用方法を記述します
プリプロセッサとは
プリプロセッサ
はコンパイル時に実行する時に走る処理を指します。
つまりは実行前に完結する処理になります。
プリプロセッサ
は#から始まる1行になります。
ここではプリプロセッサ
の一部を紹介します。
#include<stdio.h>
#include
対象のファイルを展開するプリプロセッサです。
簡単に言うなら、ファイルの中身をこのプリプロセッサ
の場所にコピペを行うような機能になります。
#include
は次の使用方法があります
#include<ファイル名>
こちらはコンパイル時に対象の場所から見たファイルを展開します。
#include"ファイル名"
こちらはコンパイル時にこのファイルのパスから見て相対パスのファイルを展開します。
ちなみにstdio.h
というのはC標準ライブラリ
の1つで標準入出力
の機能を纏められたライブラリになります。
詳しくは以下のURLを参照してください。
#define
こちらのプリプロセッサ
は指定したテキストを置き換えてコンパイルを行う機能になります。
別名にマクロと言われています。
#define
の指定方法は3 + a種類あります。
#define TEST
こちらはマクロを指定します。
#define TEST_1 10
こちらはマクロ名に紐づけられた値を指定します。
#define TEST_2(_value) _value + 10;
こちらは値に対して引数を指定することができます。
こちらでは次のような書き方もできます。
ここからは特殊な使い方になります。
#define TEST_2(_value) \
int test = _value + 10; \
test += 10
こちらは#define後に\を付けると次の行までがdefineの置換範囲になります。
\に回数指定はありません
#define TEST_TO_STRING(to_str) #to_str
マクロに入れた値を文字列に変換することができます。
#define TEST_CODE(to_str1,to_str2) to_str1 ## to_str2
マクロに入れた値をそのままコードとして連結します。
この時、VisualC/C++ではエラーはおきませんが、すべて合わせて1トークンとしておく必要があります。
以下の方も同じところに引っかかってしまったので使用する際は注意してほしい
#if #ifdef #ifndef #elif #else #endif
少し多いですが、ここは一気にまとめて説明します。
#if 0
#else
#endif
#if 値
#if
は値が真の場合#ifと特定のプリプロセッサ間に記述されたコードをコンパイルに含むプリプロセッサになります。
#if
は#if
,#ifdef
,#ifndef
のブロック内に0~1つ以上指定することができます。
終わりには必ず#endif
が必要になります。
#ifdef TEST
#elif 0
#elif 0
#elif 0
#else
#endif
#ifdef マクロ名
#ifdef
は対象のマクロが作成されている場合#ifdef
と特定のプリプロセッサ間に記述されたコードをコンパイルに含むプリプロセッサになります。
#ifdef
は#if
,#ifdef
,#ifndef
のブロック内に0~1つ以上指定することができます。
終わりには必ず#endif
が必要になります。
#ifndef TEST
#elif 0
#endif
#ifndef マクロ名
#ifndef
は対象のマクロが作成されていない場合#ifndef
と特定のプリプロセッサ間に記述されたコードをコンパイルに含むプリプロセッサになります。
#ifndef
は#if
,#ifdef
,#ifndef
のブロック内に0~1つ以上指定することができます。
終わりには必ず#endif
が必要になります。
#if
と#ifdef
と#ifndef
の説明にある特定のプリプロセッサの説明になります。
ここ以降の特定のプリプロセッサも同じものになります。
また、以下のプリプロセッサは#if
,#ifdef
,#ifndef
のサンプルコードに含まれます。
#elif 値
#elif
は#if
,#ifdef
,#ifndef
,#elif
と#endif
の間に記述できるプリプロセッサです。
#elif
前の#if
,#ifdef
,#ifndef
,#elif
が偽の場合に#elif
と特定のプリプロセッサ間にあるコードをコンパイルに含むプリプロセッサになります。
こちらは#else
,#endif
までに0~1つ以上指定することができます。
#else
#else
は#if
,#ifdef
,#ifndef
,#elif
と#endif
の間に記述できるプリプロセッサです。
こちらは#endif
1つにつき#else
は0~1つ指定することができます。
#endif
#endif
は#if
,#ifdef
,#ifndef
,#elif
,#else
の後に必ずつける必要のあるプリプロセッサです。
#if
,#ifdef
,#ifndef
,#elif
,#else
の後につけることで、これらの条件によってコンパイルに含むか含まないかのコードを区切ることができます。
必ず#if
,#ifdef
,#ifndef
と#endif
を1セットとして用意する必要があります。
実際に定義したマクロも含めて利用すると、以下のコードになります。
#include<stdio.h>
#define TEST
#define TEST_1 10
#define TEST_2(_value) _value + 10;
#define TEST_2(_value) \
int test = _value + 10; \
test += 10
#define TEST_INSERT(val1,val2) val1 = val2
#define TEST_PRINTF(val1,val2) val1(val2)
#define TEST_TO_STRING(to_str) #to_str
#define TEST_CODE(to_str1,to_str2) to_str1 ## to_str2
#if 0
#else
#endif
#ifdef TEST
#elif 0
#elif 0
#elif 0
#else
#endif
#ifndef TEST
#elif 0
#endif
int main()
{
int test = 0;
//マクロに引数をつけて代入する処理に置換する
TEST_INSERT(test,100);//->test = 100;
//関数のように利用する//
TEST_PRINTF(printf,"print"); //-> printf("print");
//マクロに入れた値を文字列に変換する//
printf(TEST_TO_STRING(10));//->"10";
int test1 = 10;
//マクロに入れた値をそのままコードとして連結する//
TEST_CODE(test,1) = 100;//->test1 = 100;
return 0;
}
終わりに
ここまでご覧くださり、ありがとうございます。
C言語やC++は行うことが少ない反面、自由度が高い言語だと思います。
今回の一連を見ていた方はC++の基礎開発も行うことができるはずです。
※ファイルの拡張子をcからcppにするだけでC++のコードと認識されます。
オブジェクト指向の話は今後も書き続けていく中で必要となるとお考えているため、次回のFlutter分の後に記載すると思います。
興味があればそちらも確認していただけると幸いです。
以上お付き合いいただき、ありがとうございました。
良いクリエイター日和を満喫してください。
Discussion