地方エンジニアの学習日記

興味ある技術の雑なメモだったりを書いてくブログ。たまに日記とガジェット紹介。

C言語の備忘録。プリプロセッサとは

プリプロセッサ

define - プリプロセッサマクロ定義

~~~c

include <stdio.h>

define COUNT 0x5

define MULTIPLE_COUNT (2 * COUNT)

define DEVIDE_COUNT(x, y) *1

int main() { printf("%d\n", COUNT); printf("%d\n", MULTIPLE_COUNT); printf("%d\n", DEVIDE_COUNT(9, 2)); } ~~~

c:実行結果 5 10 4

既定義マクロ

~~~c

include <stdio.h>

int main() { printf("LINE : %d\n", LINE); printf("FILE : %s\n", FILE); printf("DATE : %s\n", DATE); printf("TIME : %s\n", TIME); } ~~~

c:実行結果 LINE : 5 FILE : test.c DATE : Dec 1 2017 TIME : 00:00:00

undef - マクロ定義削除

~~~c

define COUNT 0x5

undef COUNT

~~~

# - 文字列化演算子

マクロ引数をダブルクォーテーションを付けた文字列に変換する

~~~c

include <stdio.h>

define COUNTB 0x6

define STRINGIFY1(x) #x

define STRINGIFY2(x) STRINGIFY1(x)

int main() { // 一段階のマクロでは引数xはマクロ展開されない printf(STRINGIFY1(COUNTB));

// 引数xのマクロ展開を先に実施するために二段階のマクロを使用
printf(STRINGIFY2(COUNTB));

} ~~~

c:実行結果 COUNTB 0x06

## - 文字列連結演算子

~~~c

include <stdio.h>

define COUNTB 0x6

define COMBINE_COUNT(x, y) x ## y

int main() { printf("%d\n", COMBINE_COUNT(COUNT, B)); } ~~~

c:実行結果 6

include - ファイルインクルード

~~~c // 標準ヘッダファイルのインクルード // 標準ヘッダファイル格納ディレクトリのみ探索

include <stdio.h>

// 作成ヘッダファイルのインクルード // カレントディレクトリ → 標準ヘッダファイル格納ディレクトリの順で探索

include "aaa.h"

~~~

if/else/elif/endif - 条件付きコンパイル

~~~c

define MODELA 0x01

if MODELA

// モデルAの処理

elif MODELB

// モデルBの処理

else

// 他のモデルの処理

endif

~~~

ifdef/ifndef - 条件付きコンパイル

~~~c:定義があれば有効

define MODELA 0x00

ifdef

// モデルAの処理

endif

~~~ ~~~c:多重インクルードガード

ifndef HELLOWOLRD_H_

define HELLOWOLRD_H_

endif / HELLOWOLRD_H_ /

~~~

error - エラーメッセージ

~~~c

define TABLE_ADDRESS 0x20000000

if (TABLE_ADDRESS % 64) != 0

error "ADDRESS ALIGNMENT ERROR"

endif

~~~

■ 宣言

記憶クラス指定子

auto

  • 局所(自動)変数であることを指定
  • 一般的には省略
  • ブロック内変数のデフォルト記憶域クラス

~~~c

include <stdio.h>

int main() { auto int count = 0; printf("%d", count); } ~~~

static

  • 関数、変数宣言時に使用
  • 関数の場合、他のファイルからのコールが不可
  • 変数の場合、静的変数であることを指定。他のファイルからのアクセスが不可

~~~c

include <stdio.h>

static int countA = 0x01;

int main() { static int countB = 0x02; printf("%d", countA); // OK printf("%d", countB); // OK }

static void sub() // 他のファイルからコール不可 { printf("%d", countA); // OK printf("%d", countB); // ビルドエラー } ~~~

register

~~~c int sub(register int a, register int b) { register int temp = 0;

for(i = 0; i < 10; i++)
{
    temp += a + b * i
}

return temp;

} ~~~

extern

  • 関数、変数宣言時に使用
  • 外部ファイルで定義された関数、変数を参照する際に指定
  • 参照側のファイルで定義

~~~c:main.c

include <stdio.h>

// 一般的にはextsub.hとして外部提供関数・変数を定義し、main.cからインクルードする extern int count; extern int sub();

int main() { printf("%d\n", count); // 10 printf("%d\n", sub()); // 20 } ~~~

~~~c:sub.c int count = 10;

int sub() { return 20; } ~~~

typedef

  • データ型に対して名前を定義

c:stdint.h typedef signed char int8_t;

関数指定子

inline

  • 関数宣言時に使用
  • コンパイラに当該関数のインライン展開を促すための通知
  • 関数呼び出しのオーバーヘッド削減になるが、オブジェクトサイズが増加する場合がある

c inline int sub() { return 20; }

型修飾子

const

  • 変数宣言時に使用
  • 当該変数が定数である場合に使用し、書き換えるとコンパイルエラーが発生する

c const int count = 100;

*1:x) / (y