😎

C言語のあれこれ9(プリプロセッサの利用方法)

に公開

はじめに

以下の記事の続きになります。

C言語のあれこれ1(Hello Worldの解読)

C言語のあれこれ2(変数と定数の作成方法)

C言語のあれこれ3(基本的な値型の種類と構造体の作成方法)

C言語のあれこれ4(関数の作成方法)

C言語のあれこれ5(計算するための演算子の説明)

C言語のあれこれ6(条件に関する演算子と条件分岐、繰り返し文の作成方法)

C言語のあれこれ7(配列を伴わないポインタの使用方法)

C言語のあれこれ8(配列を伴ったポインタの使用方法)

以下の順番で作成していきます。

追記

C言語のあれこれ8まででは1ファイル内で基本的な開発ができますが、stdio.hのようなファイルの説明はされませんでした。

じゃあ'#include<stdio.h>'とは何なのかを説明してC言語の開発方法の説明を終了します。

本編

ここではプリプロセッサの利用方法を記述します

プリプロセッサとは

プリプロセッサはコンパイル時に実行する時に走る処理を指します。
つまりは実行前に完結する処理になります。

プリプロセッサは#から始まる1行になります。
ここではプリプロセッサの一部を紹介します。

#include<stdio.h>

#include

対象のファイルを展開するプリプロセッサです。
簡単に言うなら、ファイルの中身をこのプリプロセッサの場所にコピペを行うような機能になります。
#includeは次の使用方法があります

#include<ファイル名>
こちらはコンパイル時に対象の場所から見たファイルを展開します。

#include"ファイル名"
こちらはコンパイル時にこのファイルのパスから見て相対パスのファイルを展開します。

ちなみにstdio.hというのはC標準ライブラリの1つで標準入出力の機能を纏められたライブラリになります。
詳しくは以下のURLを参照してください。
https://ja.wikipedia.org/wiki/標準Cライブラリ

#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トークンとしておく必要があります。
以下の方も同じところに引っかかってしまったので使用する際は注意してほしい
https://satosystems.hatenablog.com/entry/20101028/1288256068

#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の間に記述できるプリプロセッサです。
こちらは#endif1つにつき#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