プリプロセス指令

C のソース コードは、最初に「プリプロセス (前処理)」と呼ばれるフェーズで処理されます。以下ではすべてのプリプロセス用の指令 (ディレクティブ) について説明します。

#define name [value]

識別子 namevalueマクロ定義します。それ以降に出現する name は、すべて value に置き換えられます。name に ( ) で囲んでパラメータを付けることもできます (マクロ関数)。マクロ定義は #undef で解消できます。
#define   BUFSIZE   256
#define   max(x,y)   (x >= y ? x : y)
char buf[BUFSIZE]; // → char buf[256]; になる
a = max( b, 32 ); // → a = ((b>=32) ? b : 32); になる

#undef name

#define (またはオプション -d) で作成したマクロ定義を解消します。

#if expr1
  statements1...
[
#elif expr2
  statements2... ]...
[
#else
  statements3... ]
#endif

expr の評価結果によっていずれかの statements が実行されます (またはどの statements も実行されません)。expr は、コンパイル時に定数に評価できる式でなければなりません。expr 内では、+、-、*、/ などの算術演算子や ||、&& などの論理演算子、および defined マクロ演算子を使用できます。

#elif ブロックを任意の数だけ追加することもできます。#else ブロックは最大 1 個だけ記述できます。次のようになります。

  1. expr1 が 0 以外に評価された場合は statements1 が実行されます。
  2. #elif ブロックが存在する場合は、それまでのブロックがいずれも実行されておらず、かつ式 expr2 が 0 以外に評価されたときに限り、statements2 が実行されます。
  3. #else ブロックが存在する場合は、それまでのブロックがいずれも実行されていないときに限り、statements3 が実行されます。
  4. すべての expr が 0 に評価され、#else ブロックも存在しない場合は、どの statements も実行されません。
#if SIZE > 3
  ...
#endif

#ifdef name [value]
  statements...
#endif

#define (またはオプション -d) で name が定義されている場合に限り、statements をコンパイルします。#if と同様の #else ブロックを追加することもできます。

#ifndef name [value]
  statements...
#endif

#ifdef とは反対に、#define (またはオプション -d) で name が定義されていない場合に限り、statements をコンパイルします。#if と同様の #else ブロックを追加することもできます。

#include "path"
#include <path>

ファイル path をインクルードします。path は " " または < > で囲みます。" " を使用した場合は、path が絶対パスでなければ、次のディレクトリが順に探索されます。

  1. 呼び出し側と同じディレクトリ
  2. -pi で指定したディレクトリ
  3. 環境変数 lcinc に指定されているディレクトリ

< > を使用した場合は、1 の「呼び出し側と同じディレクトリ」は探索されません。それ以外は " " を使用した場合と同じです。
#include <stdio.h>
#include "sub\myheader.h"

#line no ["path"]

行番号とソース ファイル名を指定します。この指定は、定義済みマクロ __LINE__ および __FILE__ の値と、エラー/警告メッセージの表示に影響します。

#pragma ...

コンパイラ固有の指定を行います。Light C の #pragma 文の構文については、ここをクリックしてください。

_asm { [LC]
  ...
}

複数行のインライン アセンブラです。複数のアセンブラ命令を { } で囲んで記述します。
int x = 10;
_asm {
  mov ax,1 ; comment
  mov bx,x$ /* comment */
}

アセンブラ ブロック内では、上の例のようにアセンブラ形式のコメントも使用できます。「{」の前で改行してもかまいません。C 言語のラベルは末尾に「$」を付けて記述します。

関数形式   _asm ブロックを関数のように使用することもできます。
int x = _asm { // x に 7 が代入される
  mov ax,7
}

この場合は、} の後にセミコロン (;) が必要です。_asm ブロック末尾での AX レジスタの値が _asm ブロックの戻り値になります。

#define 名の参照   _asm ブロック内では、#define で定義したマクロおよびマクロ関数も使用できます。その場合は、C 言語の変数名を参照する場合と同様に、マクロ名の末尾に「$」を付加します。
#define REG di
#define REGS ax, bx
#define PSI( n ) word ptr [si+n]
_asm {
  mov REG$, si // = mov di, si
  mov REGS$ // = mov ax, bx
  mov PSI$(4),7 // = mov word ptr [si+4], 7
}

#define の値として   _asm ブロックは、#define の値として記述できます。パラメータを持つマクロ関数の定義にも使用できます。
#define def1 _asm { mov ax, bx }
#define def2(r) _asm { mov ax, r }

_asm ブロックに複数のアセンブラ命令がある場合は、セミコロン (;) で改行の位置を示します。次の swap のように #define 文を複数行に渡って記述する場合は、#define の構文に従って、行末に \ (バックアップスラッシュ = 円記号) を記述する必要があります。
#define def3 _asm { mov ah,9; int 21h }
#define swap(r1,r2) _asm { \
mov ax, r1 ;\
mov dx, r2 ;\
mov r1, dx ;\
mov r2, ax \

参照   #pragma asm

int _macro(param,...) { [LC]
  ...
}

インライン アセンブラのマクロを定義します。構文は #define と似ていますが、定義される内容を { } で囲んで複数行に記述する点が異なります。
_macro mov2() { // マクロ定義
  mov ax,1 ; comment
  mov bx,2 /* comment */
}
mov2(); // 呼び出し

#define 文と同じように、引数を使用できます。
_macro outv(port,val) { // マクロ定義
  mov ax, val
  out port, ax
}
int data = 10;
outv(0x60, data); // 呼び出し

「{」の前で改行してもかまいません。

アセンブラ ブロック末尾での AX レジスタの値が _macro の戻り値になります。