■ プリプロセッサ
define - プリプロセッサマクロ定義
# include <stdio.h>
# define COUNT 0x5
# define MULTIPLE_COUNT (2 * COUNT)
# define DEVIDE_COUNT(x, y) ((x) / (y))
int main()
{
printf("%d\n", COUNT);
printf("%d\n", MULTIPLE_COUNT);
printf("%d\n", DEVIDE_COUNT(9, 2));
}
実行結果
5
10
4
既定義マクロ
# 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__);
}
実行結果
LINE : 5
FILE : test.c
DATE : Dec 1 2017
TIME : 00:00:00
undef - マクロ定義削除
# define COUNT 0x5
# undef COUNT
# - 文字列化演算子
マクロ引数をダブルクォーテーションを付けた文字列に変換する
# 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));
}
実行結果
COUNTB
0x06
## - 文字列連結演算子
# include <stdio.h>
# define COUNTB 0x6
# define COMBINE_COUNT(x, y) x ## y
int main()
{
printf("%d\n", COMBINE_COUNT(COUNT, B));
}
実行結果
6
include - ファイルインクルード
// 標準ヘッダファイルのインクルード
// 標準ヘッダファイル格納ディレクトリのみ探索
# include <stdio.h>
// 作成ヘッダファイルのインクルード
// カレントディレクトリ → 標準ヘッダファイル格納ディレクトリの順で探索
# include "aaa.h"
if/else/elif/endif - 条件付きコンパイル
# define MODELA 0x01
# if MODELA
// モデルAの処理
# elif MODELB
// モデルBの処理
# else
// 他のモデルの処理
# endif
ifdef/ifndef - 条件付きコンパイル
定義があれば有効
# define MODELA 0x00
# ifdef
// モデルAの処理
# endif
多重インクルードガード
# ifndef HELLOWOLRD_H_
# define HELLOWOLRD_H_
# endif /* HELLOWOLRD_H_ */
error - エラーメッセージ
# define TABLE_ADDRESS 0x20000000
# if (TABLE_ADDRESS % 64) != 0
# error "ADDRESS ALIGNMENT ERROR"
# endif
■ 宣言
記憶クラス指定子
auto
- 局所(自動)変数であることを指定
- 一般的には省略
- ブロック内変数のデフォルト記憶域クラス
# include <stdio.h>
int main()
{
auto int count = 0;
printf("%d", count);
}
static
- 関数、変数宣言時に使用
- 関数の場合、他のファイルからのコールが不可
- 変数の場合、静的変数であることを指定。他のファイルからのアクセスが不可
# 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
- 仮引数または局所変数の宣言時に使用
- アクセス時間最適化のため、コンパイラへレジスタ割り付けのヒント情報を与える
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
- 関数、変数宣言時に使用
- 外部ファイルで定義された関数、変数を参照する際に指定
- 参照側のファイルで定義
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
}
sub.c
int count = 10;
int sub()
{
return 20;
}
typedef
- データ型に対して名前を定義
stdint.h
typedef signed char int8_t;
関数指定子
inline
- 関数宣言時に使用
- コンパイラに当該関数のインライン展開を促すための通知
- 関数呼び出しのオーバーヘッド削減になるが、オブジェクトサイズが増加する場合がある
inline int sub()
{
return 20;
}
型修飾子
const
- 変数宣言時に使用
- 当該変数が定数である場合に使用し、書き換えるとコンパイルエラーが発生する
const int count = 100;