はじめに

Light C for x86 をご使用いただき、ありがとうございます。

Light C for x86 は、Windows 95/98/NT のコマンド プロンプト内で動作する ISO/JIS/ANSI (C89) 準拠のクロス C コンパイラです。Light C で作成したコードは、各種の 8086 系組み込みシステムと、MS-DOS および Windows で実行できます。

Light C for x86 の現在のバージョンでは、8086 または 80186 プロセッサ向けのコードを生成できます。small、medium、compact、large の 4 モデルを選択でき、MS-DOS EXE ファイル、インテル HEX 形式ファイル、アセンブラのソース ファイル、または単純なバイナリ (BIN) ファイルが作成されます。

Light C では、すべての識別子を日本語で表記できます。Light C を購入された方には、標準ライブラリの全ソース コードが提供されます。

体験版の制限については、ここをクリックしてください。

Copyright © Tama Software Ltd, 1999-2010. ← → 目次 索引


このドキュメントの表記規約

このドキュメントで使用されている表記規約について説明します。

構文の表記

構文の表記は、必ずしも厳密に形式化されてはいませんが、おおよそ次の規則に準じています。

string | 斜体は、「string」自体ではなく、何か別の文字列を入力することを示します。
<文字列> | 上と同じです。< > 自体は入力しません。
[ ] | 省略可能なことを示します。[ ] 自体は入力しません。
... | 同様の指定を繰り返せることを示します。
,... | 同様の指定をカンマ (,) で区切って繰り返せることを示します。
;... | 同様の指定をセミコロン (;) で区切って繰り返せることを示します。
{a|b} | a と b のいずれかを入力することを示します。

互換性

各機能がどのような場合に使用できるのかを示すために、色付きのマークが付記されている場合があります。

[OS] | 元来 OS の API を使用する機能です。 現在の Light C では、MS-DOS または Windows で実行するコードを作成する場合には使用できますが、他のシステム向けのコードを作成する場合には使用できません。
[LC] | ISO/JIS/ANSI 規格で規定されていない Light C 固有の機能であることを特に示す場合に付記されます。
[C99] | 現在の Light C for x86 は基本的に C89 (ANSI X3.159、1989 年 12 月) に準拠しています。C90 (ISO/IEC 9899:1990 Programming Languages-C、1990 年 12 月) および日本工業規格の JIS X 3010:1993「プログラミング言語 C」も基本的に C89 と同じです。 ただし、Light C for x86 は C99 (ISO/IEC 9899:1999 Programmin Language-C Second Edition、1999 年 12 月) および JIS X 3010:2003 の仕様の一部もサポートしています。これらの C99 仕様には、このマークが付記されています。 参照 ISO/JIS/ANSI 規格との互換性

円記号とバックスラッシュ

英語環境でのバックスラッシュ (\) は、日本語環境では円記号 (\) になります。どちらも文字コードは 0x5C です。このドキュメントでは、コード表記などでバックスラッシュが表示される場合がありますが、それらは円記号と同じものです。


インストール

Light C for x86 は、Windows 95 以上または Windows NT 4.0 以上のコマンド プロンプトで使用できます。つまり、Win32 のコマンドライン環境でのみ使用でき、MS-DOS では動作しません。

  1. Light C for x86 は自己解凍型 EXE ファイル LightCSetup.exe として提供されます。LightCSetup.exe を実行して、任意のディレクトリにファイルを展開してください。
  2. Windows の [スタート] メニューから [プログラム] を選択し、[コマンド プロンプト] (MS-DOS) をクリックします。MS-DOS プロンプト ウィンドウが表示されます。
  3. ファイルを展開したディレクトリに移動します。
  4. lcenv.bat を実行して、環境変数を設定します。たとえば、C:\LC ディレクトリに展開した場合は、次のように入力します。

    c:\lc\lcenv c:\lc

インストールはこれで終了です。


簡単な使用例

付属のサンプル プログラム prime.c を例として、簡単な使い方を紹介します。 prime.c は、最初の 100 個の素数 (2 以上のどの数でも割り切れない数) を探して表示します。

単純なコンパイルと実行

Light C for x86 をインストールした後で、prime.c を現在のディレクトリに置き、次のコマンドを入力します。
lc prime

prime.c がコンパイルされ、オブジェクト ファイル prime.obj と実行ファイル prime.exe が作成されます。 次のように入力して prime.exe を実行すると、100 個の素数が表示されます。
prime

アセンブラ コードの確認

生成されたコードをアセンブラで確認するには、次のように入力します。
lc prime -fa

オプションをファイル名の前に入力したり、"-" の代わりに "/" を使用することもできます。
lc -fa prime

アセンブラ ファイル prime.asm が作成されます。このファイルを Light Macro Assembler でアセンブルすると、Light C で直接作成した場合と同じオブジェクト ファイル prime.obj が作成されます。

デバッグ

デバッグを行うには、まず、次のように入力します。
lc prime -zi

そして、デバッガ LID を次のように起動します。
lid -t4 prime

prime.c のソース コードが表示され、トレース、ダンプなどのデバッグ コマンドを入力できる状態になります。デバッガ LID の使い方については、LASM のヘルプを参照してください。-zi の代わりに -za を指定して、アセンブラ レベルでデバッグすることもできます。

LID でデバッグを行う場合は、インクルード ファイル内に宣言や定義以外の実行コードを置かないようにしてください。

複数ソース ファイルのリンク

prime.c は単一のソース ファイルから実行ファイルが作成されますが、複数のソース ファイルをリンクして、1 つの実行ファイルを作成することもできます。 たとえば、p1.c と p2.c をコンパイルして互いにリンクし、1 つの実行ファイルを作成するには、次のように入力します。
lc p1 p2 p1.c + p2.c → p1.exe

2 つの .c ファイルがコンパイルされ、互いにリンクされて、1 つの .exe ファイルが作成されます。次のように 3 つのコマンドを入力しても、同じ結果になります。
lc p1 -c | p1.c → p1.obj
lc p2 -c | p2.c → p2.obj
lil32 p1 p2 | p1.obj + p2.obj → p1.exe

次の 2 つのコマンドでも、同じ結果になります。
lc p2 -c | p2.c → p2.obj
lc p1 -linker p2 | p1.c + p2.obj → p1.exe

ワイルドカードも使用できます。一致したすべてのファイルがアルファベット順にコンパイルされ、リンクされます。
lc *.c

他のメモリ モデル

特に指定しない限り、効率のよい small モデルのコードが生成されます。small モデルに収まらない大きなプログラムを作成する場合は、-am、-ac、または -al オプションで他のメモリ モデルを指定するか、far キーワードを使って一部のコードやデータを far メモリに置く必要があります。

メモリ モデルを指定するには、たとえば、次のように入力します。
lc prime -al large モデルでコンパイル


環境変数

Light C for x86 は、次の環境変数を認識します。

環境変数 | 対象ツール | 説明
lcinc | コンパイラ | インクルード ファイルのパス (-pi に相当)。セミコロン (;) で区切って複数のパスを指定できます。
lclib | リンカ | ライブラリのパス (-pl に相当)。セミコロン (;) で区切って複数のパスを指定できます。
lcopt | コンパイラ | コマンドライン オプション
例 | set lcinc=c:\lc\inc
 | set lclib=c:\lc\lib;d:\mylib
 | set lcopt=-186 -am

lcopt

毎回同じコマンドライン オプションを指定する場合は、lcopt を使用すると便利です。lcopt に指定したオプションは、コマンドラインに自動的に連結されます。lcopt に指定したオプションと、実際にコマンドラインに指定したオプションが競合する場合は、コマンドラインに指定したオプションが優先されます。


コマンドライン形式

lc.exe のコマンドライン形式は、次のとおりです。

lc src_files... [-options]...
[-linker linker_commands...] [@response_file...]

src_files には、C 言語のソース ファイル名を指定します。拡張子を省略すると、自動的に「.c」が補われます。

-options には、必要に応じてコンパイル オプションを指定します。

ソース ファイル名とオプションの順番は原則として自由ですが、-linker の後に指定したソース ファイル名とオプション (上の linker_commands) は、そのままリンカ lil32.exe に渡されます。

先頭に「@」を付けて応答ファイルを指定できます (上の response_file)。応答ファイルには、コマンドライン オプションとソース ファイル名をコマンドラインで指定するときと同じ形式で記述します。

複数のソース ファイル名を指定すると、各ソース ファイルがコンパイルされた後、互いにリンクされます。

コンパイルだけを行うには、-c を指定します。コンパイルせずにリンクだけを行うには、-l を指定します。


コンパイル オプション

オプションを使ってコンパイル方法を変更できます。

オプションは「-」または「/」で開始し、必要に応じてコロン (:) と値を付加します。個々のオプションの構文は、次のとおりです。

{-|/}option-name[:value]

option-name の大文字と小文字は、区別されません。

数値を指定するオプションの場合、「:value」を省略すると、「:1」を指定したものと見なされます。-c や -hex のようにオンとオフの区別しかないオプションは、「:1」を指定するとオンになり、「:0」を指定するとオフになります。数値には 0xnn 形式で 16 進数を指定することもできます。

-pi や -fa のように、数値ではなく文字列を指定するオプションもあります。-fp のように値の文字列を省略できるオプションもあります。

競合するオプションを同時に指定した場合は、後で指定したオプションが優先されます。
lc test.c -al -as | ← -as が -al を打ち消す
lc test.c -o -or:0 | ← 最適化するがレジスタ変数は使用しない

「lc -?」と入力すると、すべてのオプションが一覧表示されます。

  • 一般的なオプション
  • ソース ファイルの記述方法を規定するオプション
  • 生成ファイルを指定するオプション
  • 生成コードを変更するオプション
  • 最適化オプション
  • エラー、警告、デバッグ オプション


一般的なオプション

オプション | 既定値 | 説明
-c | 0 | コンパイルのみ行ってリンクしません。既定では、自動的にリンクまで行われます。
-l | 0 | コンパイルを省略して、リンクだけを行います。
-linker | このオプションより後のファイル名とオプションを、そのままリンカ lil32.exe に渡します。-linker の後には、オブジェクト ファイル名と lil32.exe のリンカ オプションを指定します。
-pi:dir[;...] | インクルード ファイルの検索パスを指定します。セミコロン (;) で区切って複数のパスを指定できます。-pi オプション自体を複数個指定することもできます。このオプションには、環境変数 lcinc と同じ効果があります。
-pl:dir[;...] | ライブラリ ファイルの検索パスを指定します。セミコロン (;) で区切って複数のパスを指定できます。-pl オプション自体を複数個指定することもできます。このオプションには、環境変数 lclib と同じ効果があります。
-zl | 0 | アセンブラ コードに IncludeLib 文を出力しません。この結果、既定のライブラリ検索パスがオブジェクト ファイルに含まれせん。
-silent | 0 | サイレント モードです。コンパイル時の表示が最小限に抑えられます。
-dspcl | コンパイル中のファイル名と行番号を表示します。
-ptrdist:n 0 エラー メッセージにポインタの near、far 属性を表示する方法を指定します。
  • far のみ表示 (既定値)
  • small モデルでの far ポインタ、large モデルでの near ポインタなど、既定以外の属性のみ表示
  • すべて表示
-? すべてのオプションを画面に一覧表示します。
-?err | すべてのエラーおよび警告メッセージを画面に一覧表示します。
-?key | Light C が認識するすべてのキーワードを画面に一覧表示します。


ソース ファイルの記述方法を規定するオプション

オプション | 既定値 | 説明
-d:name[=value] |  | ソース ファイルに「#define name value」と記述することと同じです。
-j | 0 | char 型を unsigned char 型と見なします。既定では、char 型は signed char 型と見なされます。ただし、このオプションを指定しても CHAR_MIN と CHAR_MAX の値は変化しません。
-nc |  | コメント /* ... */ の入れ子を許可します。
-ansi | 0 | ISO/JIS/ANSI 規格外の機能を無効にします。-ansikey、-ansidec、-ansicom を合わせた効果があります。
-ansicom | 0 | // で始まるコメントを使用禁止にします。→ ISO/JIS/ANSI 規格との互換性
-ansidec | 0 | コードの途中や for 文の初期化式で変数を宣言することを禁止します。→ ISO/JIS/ANSI 規格との互換性
-ansikey | 0 | ISO/JIS/ANSI 規格外のキーワードを無効にします。far、near、pascal、stdcall、syscall が無効になります。
-os:{dos|none} | dos | ターゲット OS を指定します。none を指定すると、OS に依存する関数 (printf など) が使用できなくなります。


生成ファイルを指定するオプション

オプション | 既定値 | 説明
-bin | 0 | バイナリ (.bin) ファイルを出力します。このファイルでは、生成されたコードが単純に先頭から並べられます。
-hex | 0 | インテル HEX 形式ファイルを出力します。作成したコードを ROM 化する場合などに指定します。Z80 版では既定で *.hex ファイルが出力されます。
-fe:fname |  | 作成される実行 (.exe、.bin、.hex) ファイルの名前を指定します。fname にディレクトリ名を指定すると、そのディレクトリに既定のファイル名で実行ファイルが作成されます。フルパスを指定することも、ファイル名だけを指定することもできます。
-fo:fname |  | 作成されるオブジェクト (.obj) ファイルの名前を指定します。複数のソース ファイルをコンパイルする場合は、ディレクトリを指定します。
-fa[:fname] |  | アセンブラ (.asm) ファイルを作成します。オブジェクト ファイルも作成されます。fname を省略すると、ソース ファイルの拡張子を「.asm」に置き換えたファイルが作成されます。
-ca[:fname] |  | アセンブラ (.asm) ファイルだけを作成し、オブジェクト ファイルは作成しません。
-masm | 0 | -fa 指定時に、MS-MASM 6.0 でアセンブルできるアセンブラ ファイルを作成します。このオプションを指定しないと、LASM 特有の option 文などが挿入されます。このオプションを指定した場合は、アセンブル時に明示的にライブラリのパスなどを指定する必要があります。
-useas | 0 | アセンブラの public/extern/comm 文で as キーワードを使用します。アセンブラ ファイル内では、パブリック名にも「$」が付加されます。たとえば、text() という公開関数は、通常ならアセンブラ ファイル内でも外部名と同じ「_text」で表されますが、このオプションを指定すると、「text$」で表されます。このオプションを使用すると、セグメント/グループ名と関数/変数名が同じ場合に、名前の競合を避けることができます。
-fp[:fname] |  | プリプロセス処理後の C 言語ファイル (*.pp) を作成します。オブジェクト ファイルは作成されません。
-kcp | 0 | -fp で作成されるプリプロセス ファイルに、元のソース ファイルに記述されていたコメントを残します。
-fl[:fname] |  | 機械語リスト (.lst) ファイルを作成します。
-fm[:fname] |  | リンク マップ (.map) ファイルを作成します。
-tab:n | 8 | タブサイズを何桁と見なして、アセンブラ ファイル、機械語リスト ファイル、およびマップ ファイルを作成するかを指定します。
-coli:n | 16 | アセンブラ ファイルに、「mov」などの命令 (インストラクション) を何桁目から記述するかを指定します。
-cold:n | 24 | アセンブラ ファイルに、「word ptr _abc」などのオペランド部分を何桁目から記述するかを指定します。
-colc:n | 56 | アセンブラ ファイルに、ソース ファイルの行番号などを示すコメントを何桁目から記述するかを指定します。


生成コードを変更するオプション

オプション | 既定値 | 説明
-as、-am、-ac、-al | -as | メモリ モデルを指定します。-as は small、-am は medium、-ac は compact、-al は large モデルを指定します。
-emul | 0 | 浮動小数点演算エミュレータを使用します。 このオプションで生成したコードは、低速ですが、浮動小数点演算コプロセッサ (FPU) が実装されていないマシンでも実行できます。 浮動小数点演算を使用しないプログラムでは、このオプションは指定しないことをお勧めします。エミュレータのコードがリンクされないため、その方がプログラムが小さくなります。
-stk:n |  | 追加スタック サイズを 10 進数で指定します。リンカ Lil.exe の -tsd オプションに相当します。既定のスタック サイズは、4096 バイトです。このオプションを指定すると、4096 + n バイトのスタックが確保されます。ライブラリ ファイル start.asm を編集すれば、既定のスタック サイズを変更できます。
-alignloc:n | 2 | スタック上に作成される局所変数のアライン サイズを指定します。たとえば、既定値の 2 では、2 バイト以上のデータは必ず 2 で割り切れるアドレスに配置されます。
-alignst:n | 2 | 構造体メンバのアライン サイズを指定します。アライン方法は、上の -alignloc と同様です。
-csp | 0 | コード セグメントのアラインを word (2B) ではなく para (16B) にします。
-pad:n | 0 | -alignst によるアラインで生じた隙間を埋めるバイトを指定します。0 ～ 255 を指定します。
-evall | 0 | 二項演算のオペランドをできるだけ左から評価します。→ 演算子
-evalr | 0 | 二項演算のオペランドをできるだけ右から評価します。
-segn:seg:name |  | セグメント名を指定します。seg には、code、data、const、bss、stack のいずれかを指定します。[KC160]
-segfn:seg:name |  | FAR セグメントの名前を指定します。seg には、code、data、const、bss、stack のいずれかを指定します。[KC160]
-segc:seg:name |  | セグメント クラス名を指定します。[KC160]
-segfc:seg:name |  | FAR セグメントのクラス名を指定します。[KC160]
-segfv | 0 | far セグメントのコンバイン属性を public ではなく private にします。これにより、同じ名前の far セグメントが連結されなくなります。同じ名前の far セグメントが連結され、サイズ 64 KB を超えてエラーが発生する場合は、このオプションが役立ちます。[KC160]
-sjt | 1 | 大きな switch 文をコード化するとき、ジャンプテーブルを使用します。これにより、生成コードが高速化され、コード サイズが減少します。
-lss | 0 | スタック上の局所変数にアクセスする際、既定の DS ではなく SS レジスタを使用します (-al、-ac 指定時)。スタック切り替えを伴うプログラムのためのオプションです。プログラムの実行速度は低下します。 ライブラリ関数を使用する場合は、そのライブラリ関数をこのオプションで再コンパイルする必要があります。また、アセンブラで書かれているライブラリ関数の一部 (_eml_mul 等) は、このオプションに対応していません。


最適化オプション

オプション | 既定値 | 説明
-8086、-186 | -8086 | ターゲット CPU を指定します。既定は -8086 です。-186 を指定すると、効率がよく、ただし 8086 では実行できないコードが生成されます。[KC160]
-gs | 0 | 実行時のスタック オーバーフロー検査を省略し、より小さく高速なコードを生成します。詳細については、ランタイム エラー「R.1010 stack overflow」の説明を参照してください。
-gf | 0 | 同一の文字列定数 ("...") を同じメモリ域に配置します。このオプションを指定すると、データ サイズが減少しますが、文字列定数を変更するプログラムでは変更が他の文字列に影響するため、このオプションを使用するとプログラムの動作が変わる可能性があります。
-o | 0 | すべての安全な最適化を行います。-onp 以外のすべての最適化が有効になり、-gs が指定されます。
-oasm | 0 | 一部のアセンブラ命令をより効率のよい命令に置き換えます。たとえば、乗算命令をシフト命令に変更します。
-odn | 0 | 恒等式を消去します。たとえば、定数 0 の加算や 1 の乗算を省略します。
-ogc | 0 | 連続して実行される同一の条件判断を 1 つにまとめます。
-oge | 0 | 同じ式の繰り返しを 1 つにまとめます。
-ogl | 0 | ループを組み替えて、ジャンプ命令を減らします。
-omisc 1 細かい各種の最適化を行います。次の最適化オプションをすべて指定することと同じです。
  • -opt1 後置 ++/-- 演算の効率化
  • -opt2 レジスタ退避コードの削減
  • -opt3 レジスタ選択の最適化
  • -opt4 レジスタ/メモリ間の代入の削減
  • -opt5 条件の反転によるジャンプの効率化
  • -opt6 参照されないラベルの削減
-onp 0 near ポインタを far ポインタに変換するときに near ポインタが NULL 値かどうかをチェックするコードを省略します。この場合、コードの効率は上がりますが、実行時に NULL 値の near ポインタを far ポインタに変換したとき、far ポインタは NULL になりません。

small/medium モデルを使用し、かつ far ポインタを使用していない場合、このオプションの効果はありません。compact/large モデルでは、局所変数のアドレスなどが暗黙で near になるため、このオプションの影響を受けます。

-or | 0 | register キーワードが指定されていない変数についても、可能な場合はレジスタ変数を自動的に割り当てます。


エラー、警告、デバッグ オプション

オプション | 既定値 | 説明
-re:n | 2 | エラー発生時の終了コードを指定します。
-rw:n | 0 | 警告発生時の終了コードを指定します。
-errd | 1 | エラー メッセージを詳細に表示します。一部のメッセージがより詳しく表示されます。
-errmax:n | 20 | 指定の数のエラーが発生したら、コンパイルを中止します。
-errcon:n |  | 指定の数のエラー/警告が発生するたびに、キー入力を待機します (スクロール防止用)。
-wn:n |  | 特定の番号の警告を抑止します。このオプションは、いくつでも指定できます。
-wenum | 0 | 通常、列挙 (enum) 型は int 型と同じように扱われますが、このオプションを指定すると、列挙型が独自の型と見なされ、他の型との変換が警告されます。ただし、列挙型から int 型への変換は、常に許されます。このオプションは、特定の用途でしか使用できない列挙値を別の変数に代入する誤りを検出するために用意されています。
-wnt | 0 | 数値の型変換を厳密にチェックします。通常は、unsigned int と signed int など、同じサイズの数値型では、符号付きと符号なしの間の型変換は (値を失う可能性があるにもかかわらず) チェックされません。このオプションを指定すると、そのような変換も警告されます。
-wncs | 0 | const 属性の有無のチェックを無効にします。
-zh | 0 | C 言語レベルのデバッグ情報を .dbg ファイルに出力します。-fm も指定した場合は、マップ ファイルにもデバッグ情報が出力されます。生成される実行 (.exe/.hex/.bin) ファイルは変わりません。付属のデバッガ LID を使用する場合は、-zi を使用してください。
-zah | 0 | -fh と同じですが、C 言語レベルではなく、アセンブラ レベルのデバッグ情報を出力します。


文法概要

このドキュメントには C 言語文法の仕様と Light C 固有の拡張および制限が記載されています。必ずしも C 言語の入門書ではありませんので、C 言語の一般的な書き方を学ぶ場合は、市販の入門書なども参照することをお勧めいたします。

プリプロセス

C そソース ファイルは、最初にプリプロセスという前処理が適用され、その結果生成されたコードが C の構文解析にかけられます。

参照 プリプロセス指令、プリプロセス演算子、-pi オプション、-fp オプション

C ソース コードの構成

C のソース ファイルはトークン (token, 字句) の連続です。トークンは次のいずれかです。

トークン | 説明
キーワード | for や if など、特定の意味を持つ予約語
名前 (識別子) | 変数名、関数名など、ユーザーが定義する識別子
リテラル | 10 や "abc" などの定数データ表現
演算子 | =、+、[] など
区切り子 | キーワードや名前などを分離するための文字 (列) で、それ以外の役割を持ちません。ホワイトスペース (スペース文字、タブ、改行など) またはコメントのいずれかです。

トークンの一定の連続が関数や変数の宣言を構成します。このレベルで見ると、C のソース ファイルは関数宣言・定義と変数宣言の集まりです。

関数内には文 (ステートメント) を記述します。文は次のいずれかです。
構文 | <宣言> ;
 | <式文> ;
 | <制御文>
 | <ブロック>

ここで <ブロック> は、任意の数の文の並びを { } で囲んだものです。
例 | int a; | // 宣言
 | a = 1; | // 式文
 | if ( x ) a++; | // 制御文
 | if ( x ) { a++; } | // ブロックを含む制御文 (上と同じ効果)


三文字表記

国によっては、一部の記号を入力できないため、代替手段として次の三文字表記 (trigraph sequence) が用意されています。日本ではあまり使用されません。

三文字表記 | コード | 英語圏での文字
??= | 23 | #
??( | 5B | [
??/ | 5C | バックスラッシュ
??) | 5D | ]
??' | 5E | ^
??< | 7B | {
??! | 7C | |
??> | 7D | }
??- | 7E | ~
例 |
 | ??=include <stdio.h> | // #include <stdio.h>
 | char buf??(100??); | // char buf[100];


エスケープ シーケンス

文字列リテラルおよび文字リテラルでは、次のエスケープ シーケンス (escape sequence) を使用できます。

表記 | コード | 説明
\' | 27h | 一重引用符 (' ' 内で)
\" | 22h | 二重引用符 (" " 内で)
\? | 3Fh | 疑問符
\\ | 5Ch | 円記号
\0 | 00h | ヌル文字 (NUL)
\nnn |  | nnn が 0 ～ 7 ならば 8 進数で指定されたバイト。最大 3 桁です。3 桁以内に 8 進数として解釈できない文字があったときは、そこでエスケープ シーケンスの処理が止まります。
\a | 07h | アラーム (BEL)
\b | 08h | バック スペース (BS)
\f | 0Ch | フォーム フィード (FF)
\n | 0Ah | 行送り、ライン フィード (LF)
\r | 0Dh | 復帰、キャリッジ リターン (CR)
\t | 09h | タブ (HT)
\xnnn |  | 16 進数で指定されたバイト列。nnn には、1 文字以上の 16 進文字 (0 ～ F) を指定します。エスケープ シーケンスの処理は、16 進数として解釈できない文字があったところで止まります。文字列で、直後の 16 進文字をエスケープ シーケンスとして処理させないためには、文字列を区切ります。 例 "\x41" "BC" // = "ABC"
\v | 0Bh | 垂直タブ (VT)


キーワード、名前、コメント

キーワード

Light C では、次の文字列がキーワード (予約語) として識別されます。

_asm _far _macro _near _interrupt _pascal _stdcall _syscall auto break case char const continue default do double else enum extern far float for goto if int interrupt long near pascal register return short signed sizeof static stdcall struct switch syscall typedef union unsigned void volatile while

  • キーワードの大文字と小文字は区別されます。
  • 先頭に下線 (_) が付いているキーワードは ISO/JIS/ANSI 規格外です。inline も C++ 規格ではありますが C (C89、C99) の規格ではありません。
  • 赤色のキーワードは ISO/JIS/ANSI 規格外です。赤色のキーワードは、-ansi を指定すると無効になります。
  • lc.exe にオプション -?key を指定すると、すべてのキーワードが一覧表示されます。

名前

A～Z、a～z、0～9、_ で構成されるキーワード以外の識別子 (identifier) です。先頭文字は数字であってはなりません。変数名、関数名、構造体タグ名、構造体メンバ名、列挙名、ラベル、型定義名、マクロ名として自由に使用できます。また、Light C では、半角カタカナおよび Shift-JIS 全角文字も、名前として使用できます。→ 日本語表記

名前の大文字と小文字は区別されます。

名前の例 | 有効か | 理由
A | 有効 |
A2B | 有効 |
_X3_4 | 有効 |
3A | 無効 | 先頭が数字
A@ | 無効 | 「@」は使用できない
合計金額 | 有効 [LC] | 日本語

コメント

例 | /* これはコメント */
 | /* これも ...
 | ...
 | コメント */
 | // これはコメント [C99]

/* と */ で囲まれた間の部分と、// から改行までの部分は、任意のコメントを書くことができます。コメントはプログラムに影響しません。

ただし、文字列リテラル "..." の中にある /*、*/、// は、コメント記号としては認識されません。


整数リテラル

構文 [+|-][0x|0|0q|0b][0123456789ABCDEF]...[U|u|L|l]
例 | 123 | 10 進数の 123
 | -123 | 10 進数の -123
 | 0x123 | 16 進数の 123 = 10 進数の 291
 | 0123 | 8 進数の 123 = 10 進数の 83
 | 0q123 | 4 進数の 123 = 10 進数の 27 [LC]
 | 0b1001 | 2 進数の 1001 = 10 進数の 9 [LC]
 | -0xFF | 16 進数の -FF = 10 進数の -255
 | 123U | unsigned 型の 123
 | 123L | long 型の 123
 | 0x12ul | unsigned long 型の 0x12

基数

先頭に 0x、0、0q、0b を付けると、それぞれ 16 進数、8 進数、4 進数、2 進数になります。4 進数と 2 進数は ISO/JIS/ANSI 規格外です。16 進数では、10 ～ 15 の桁を 'A' ～ 'F' または 'a' ～ 'f' で表します。

型

末尾に u または U を付けると、unsigned (符号なし) 型になります。末尾に l または L を付けると、long 型になります。両方指定すると、unsigned long 型になります。いずれも指定しないと、int 型と見なされますが、int 型に入りきらない場合は、値に応じて unsigned、long、unsigned long 型と見なされます。→ 型
例 |
 | short a = 1234; | 有効
 | short b = 40000; | 40000 は short に収まらないので警告される
 | short c = 123L; | long を short に代入したので警告される
 | char d = 100; | 100 は char に収まるので警告されない
 | char e = 300; | 警告される

参照 リテラル

Copyright © Tama Software Ltd, 1999-2010. ← → 目次 索引


浮動小数点数リテラル

浮動小数点数 (floating point number) リテラルにより、IEEE 浮動小数点数を定義できます。
構文 | 1 [+|-][digits][.digits][{e|E}[+|-]digits][F|f|L|l]
 | ※ digits は 0,1,2,3,4,5,6,7,8,9 の 1 つ以上の連続
構文 | 2 [+|-]0x[hdigits][.hdigits][p[+|-]digits] [C99]
 | ※ hdigits は 0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F,a,b,c,d,e,f の 1 つ以上の連続
例 | 3.14 | // 3.14
 | .1 | // 0.1
 | . | // 不可
 | 100. | // 100.0
 | 0.314e+1 | // 3.14
 | 0.314e+2 | // 31.4
 | 314e-2 | // 3.14
 | 3.14F | // float 型の 3.14

指数表現

e または E を含めることにより、指数表現を使用できます。"int.decEexp" と記述すると、int.dec × (10 の exp 乗) が値になります。

型

末尾に f または F を付けると、float 型になります。末尾に l または L を付けると、long double 型になります。いずれも指定しないと、double 型と見なされます。→ 型


文字と文字列

文字リテラル

構文 | 'x'
 | L'x'
例 | '1' | // int 型の 0x31
 | 'A' | // int 型の 0x41
 | 'AB' | // エラー
 | 'あ' | // エラー
 | '' | // エラー
 | '\n' | // 改行文字を表す (int 型の 0x0A)
 | '\\' | // 文字 \ を表す (int 型の 0x5C)
 | L'あ' | // ワイド文字 (unsigned short 型の Shift-JIS 全角文字コード (0x82A0))
 | L'A' | // ワイド文字 (unsigned short 型の Shift-JIS 文字コード (0x0041))

文字 (character) リテラル (文字定数) は int 型と見なされます。ただし、値が char 型に収まるため、文字定数は警告を受けることなく char 型にも代入できます。改行や '\' など、一部の文字は、エスケープ シーケンスを使って表現します。

先頭に 'L' を付けると、wchar_t 型のワイド文字になります。

文字列リテラル

例 | "1" | // 31, 00
 | "123" | // 31, 32, 33, 00
 | "123\n" | // 31, 32, 33, 0A, 00
 | "" | // 00 (空文字列)
 | "12" "3" | // 31, 32, 33, 00 (文字列の連結)
 | L"あか"; | // ワイド文字列

文字列 (string) リテラルは、char [ ] 型の配列として扱われます。末尾には自動的に 0 が付加されます。ただし、長さが 1 だけ不足する配列の初期化に使用されたときは、0 は付加されません。

複数の文字列リテラル ("～" の表記) がスペース、改行、コメントを挟むだけで隣り合っていると、自動的に連結され、1 つの文字列になります。

先頭に 'L' を付けると、wchar_t [ ] 型のワイド文字列になります。
例 | char buf1[4] = "123"; | // 31,32,33,00
 | char buf2[4] = "1234"; | // 31,32,33,34
 | char buf3[4] = "12"; | // 31,32,00,00
 | char buf4[] = "1234"; | // 31,32,33,34,00
 | int a1 = sizeof( buf1 ); | // a1 = 4
 | int a2 = sizeof( buf4 ); | // a1 = 5

ワイド文字

ISO/JISANSI では 16 ビット文字コード用に wchar_t という型が用意されています。wchar_t 型は、stddef.h で unsigned short int に定義されています。ワイド文字 (列) リテラルは、通常の文字 (列) の先頭に「L」を付けることで表現します。
例 | wchar_t a = L'赤'; | // ワイド文字
 | wchar_t b = L"あかさたな"; | // ワイド文字列

Light C では、ワイド文字リテラルは Shift-JIS コードを表します。全角文字の場合は、上位 8 ビットに漢字コードの第 1 バイトが、下位 8 ビットに漢字コードの第 2 バイトが格納されます。半角文字の場合は、下位 8 ビットにデータが格納され、上位 8 ビットは 0 になります。

printf 系関数の %C および %c 指定子では、通常の ASCII 半角文字だけでなく、上の形式の全角文字も出力できます。
例 printf( "%C", L'赤' );

printf 系関数で wchar_t の文字列を出力するには、%S 指定子を使用します。
例 printf( "%S", L"あかさたな" );

参照 多バイト/ワイド文字関数

Copyright © Tama Software Ltd, 1999-2010. ← → 目次 索引


プリプロセス指令

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

#define name [value]

識別子 name を value にマクロ定義します。それ以降に出現する 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 の戻り値になります。


#pragma

#pragma 指令は、コンパイラ固有の指定を行う手段として ISO/JIS/ANSI 規格で定められています。#pragma 文の構文は、コンパイラによって異なります。 Light C では、以下の #pragma 文を使用できます。これ以外の #pragma 文は、無視されます。

#pragma asm asm-line [LC]

単一行のインライン アセンブラです。asm-line がそのままアセンブラ コードに挿入されます。アセンブラ コードでは、特定のレジスタ値を保存する必要があります。
例 | #pragma asm int 0h
 | #pragma asm mov [var$], ax
 | _asm inc cl

asm-line の構文が適切でない場合は、コンパイラ内部のアセンブラがエラー メッセージを表示します。 アセンブラ コード内では、C 言語の変数名とラベルも使用できます。C 言語の名前は、末尾に「$」を付加して記述します。 複数の命令を含むアセンブラ ブロックを記述する場合は、_asm を使用するか、複数の #pragma asm を続けて記述してください。

参照 _asmcode

#pragma echo message [LC]

message を画面に表示します。message にマクロ名が含まれている場合は、プリプロセス処理後の結果が表示されます。
例 #pragma echo 行番号 = __LINE__

#pragma segment [name [class-name]] [LC]

far 型のデータおよびコードを配置するセグメントを指定します。name および class-name を省略すると、再び既定のセグメント名が使用されます。
例 | #pragma segment SEG1 CLASS1
 | int far buf1[100]; | // SEG1 に置かれる
 | void far sub1() { } | // SEG1 に置かれる
 | #pragma segment
 | int buf2[100]; | // 通常のセグメントに置かれる
 | void sub2() { } | // 通常のセグメントに置かれる


プリプロセス演算子

defined 演算子

構文 defined( name )

#if 文中で使用できるマクロ演算子で、name がマクロ名として #define されていれば 1 に、そうでなければ 0 に評価されます。#if defined(...) は #ifdef ... と同じですが、#if defined(...) では下の例のように複数の名前を判定に使用できます。
例 #if defined(NAME1) || defined(NAME2)

行継続

プリプロセス行 (# で始まる行) の最後に \ (円記号＝バックスラッシュ) を記述すると、その直後の改行は存在しないものとして扱われます。
#define name (1+2+3+4+ \
5+6+7+8+9)


定義済みマクロ

次のマクロは、コンパイラ内部で暗黙に定義されます。

マクロ | 値の例 | 説明
__FILE__ | "test.c" | 現在のソース ファイル名です。この値は #line 文で変更できます。
__LINE__ | 12 | 現在のソース ファイルの行番号です。番号は 1 から始まります。この値は #line 文で変更できます。
__DATE__ | "Jul 14 1999" | コンパイルした日付です。
__TIME__ | "09:45:01" | コンパイルした時刻です。
_FAR_DATA [LC] | (なし) | compact および large モデルに限り、空の値に定義されます (つまり、暗黙で「#define _FAR_DATA」が実行されます)。それ以外の場合は、定義されません。
_FAR_CODE [LC] | (なし) | medium および large モデルに限り、空の値に定義されます。
_FP_EMUL [LC] | (なし) | オプション -emul を指定すると、空の値に定義されます。
_OS_NONE [LC] | (なし) | オプション -os:none を指定すると、空の値に定義されます。
_ANSI_KEYWORD [LC] | (なし) | オプション -ansikey を指定すると、空の値に定義されます。
_LC_VERSION [LC] | "1.42" | Light C のバージョンを表す文字列です。

ヘッダー ファイルのマクロ定義

ヘッダー ファイルで定義されている主なマクロ識別子を示します。

識別子 | 値 | ファイル | 説明
NULL | 0 | stddef.h | NULL ポインタ
HUGE_VAL | 1.0e+309 | math.h | 浮動小数点数のオーバーフロー値 (実際の数値は、もう少し小さな値です)
INT_MIN | -32768 -0x8000 | limits.h | int 型の最小値
INT_MAX | 32767 0x7FFF | limits.h | int 型の最大値
CHAR_MIN | -128 -0x80 | limits.h | char 型の最小値 (-j では変化しません)
CHAR_MAX | 127 0x7F | limits.h | char 型の最大値 (-j では変化しません)
SCHAR_MIN | -128 -0x80 | limits.h | signed char 型の最小値
SCHAR_MAX | 127 0x7F | limits.h | signed char 型の最大値
UCHAR_MAX | 255 0xFF | limits.h | unsigned char 型の最大値
SHRT_MIN | -32768 -0x8000 | limits.h | short 型の最小値
SHRT_MAX | 32767 0x7FFF | limits.h | short 型の最大値
USHRT_MAX | 65535 0xFFFF | limits.h | unsigned short 型の最大値
LONG_MIN | -2147483648 -0x80000000 | limits.h | long 型の最小値
LONG_MAX | 2147483647 0x7FFFFFFF | limits.h | long 型の最大値
ULONG_MAX | 4294947295 0xFFFFFFFF | limits.h | unsigned long 型の最大値
FLT_xxx |  | float.h | float 型の最大値、精度など
DBL_xxx |  | float.h | double 型の最大値、精度など
EXIT_SUCCESS | 0 | stdlib.h | 正常終了時の終了コード
EXIT_FAILURE | 2 | stdlib.h | エラー終了時の終了コード
MB_CUR_MAX | 2 | stdlib.h | 多バイト文字の最大サイズ
RAND_MAX | 32767 0x7FFF | stdlib.h | rand() から返される最大値
SIGxxx |  | signal.h | signal() で使用
NDEBUG |  | assert.h | 定義すると assert() が無効になる (既定では未定義)
CLOCKS_PER_SEC | 1000 | time.h | clock() で使用
CLK_TCK | 1000 | time.h | CLOCKS_PER_SEC の過去の表現
EOF | -1 | stdio.h | ファイルの終端
FILENAME_MAX | 255 | stdio.h | ファイル名の最大長
L_tmpnam | 14 | stdio.h | tmpnam() が生成する一時ファイル名の最大長
FOPEN_MAX | 10000 | stdio.h | 同時に開けるファイルの数 ※1
TMP_MAX | 1000 | stdio.h | tmpfile() および tmpnam() で重複しない名前が保証される一時ファイルの数
SEEK_xxx |  | stdio.h | fseek() で使用
_IOxBUF |  | stdio.h | setvbuf() で使用
BUFSIZ | 256 | stdio.h | setbuf() で使用

※1 Light C は同時にオープンできるファイル数を制限しませんが、OS がファイル数を制限する場合があります。

マクロ関数は、「ライブラリ関数」に一般の関数と一緒に記載されています。


宣言

関数と変数は、使用する前にその型と名前を宣言する必要があります。宣言の構文は次のとおりです。
構文 [storage-class] [type-qualifier]... type-specifier declarator [= initializer]

ここで storage-class には最大 1 つの記憶クラスを指定します。type-qualifier には任意の数の型修飾子を指定します。型指定子 type-specifier は次のいずれかです。
構文 | [signed | unsigned] [long | short] [int] | // 2～4 バイトの整数
 | [signed | unsigned] char | // 1 バイトの整数
 | float | double | long double | // 浮動小数点数
 | void
 | struct [tag] [{ declarator... }] | // 構造体
 | union [tag] [{ declarator... }] | // 共用体
 | enum tag | // 列挙

signed、unsigned、long、short を 1 つ以上指定した場合、int は省略できます。

宣言子 declarator は次のいずれかです。
構文 | name | // 変数名
 | * declarator | // ポインタ
 | declarator [ number ] | // 配列
 | declarator ( [arguments]... ) | // 関数宣言
 | [type-qualifier]... declarator [type-qualifier]...

ここで name は変数名、number は配列の要素数です。* はポインタ、[ ] は配列の宣言で使用します。( ) は関数や関数へのポインタの宣言で使用し、arguments はその関数の引数です (省略可)。

初期化子 initializerは次のいずれかです。宣言した変数の型と一致する必要があります。
構文 | <整数リテラル>
 | <浮動小数点数リテラル>
 | <文字リテラル>
 | <文字列リテラル>
 | <式>
 | <値リスト>

広域変数や静的変数の初期化では、定数 (または定数だけからなる式 ) しか使用できませんが、局所変数の初期化では、変数や関数呼び出しを含む式も使用できます。

<値リスト> は { } の中に宣言をカンマで区切って並べたもので、構文は次のとおりです。
構文 { <宣言> ,... }

値リストは、配列または構造体の初期化に使用します。

参照

  • 関数
  • 変数


変数

変数とは

変数 (variable) はデータ値を入れておく「入れ物」です。変数には値を設定したり、そこから値を取得したり、値を変更することができます。
例 | int a, b;
 | a = 123; | // a に 123 を設定する
 | b = a; | // a の値 (123) を取得して、b に設定する
 | b = a + b; | // a + b の値 (123 + 123 = 246) を b に設定する
 | b += 10; | // b の値を 10 増やす (256 になる)

変数の宣言

変数は、使用する前に宣言する必要があります。変数宣言の例をいくつか示します。
例 | int a; | // 整数の宣言
 | static int b; | // 静的変数の宣言
 | const int c; | // 定数の宣言
 | char* d; | // 文字へのポインタ (文字列) の宣言
 | char** e; | // 文字へのポインタ (文字列) へのポインタの宣言
 | struct { int a; char* p; } f; | // 構造体の宣言
 | int (*g)(); | // int を返す関数へのポインタの宣言

変数の宣言は、関数内でも関数外でも可能です。

関数内で宣言する場合は、実行文 (式文や制御文) の後に宣言文を置くこともできます。[C99]
例 | void func( int a ) {
 | a++;
 | int b; | // 実行文 a++ の後で宣言を行う
 | ...

変数のスコープ

変数は、関数の中で宣言することも、関数の外で宣言することもできます。変数を宣言した場所と、記憶クラス static によって、その変数のスコープ (有効範囲、つまり変数を使用できる範囲) と、変数の生存期間が次のように決まります。

宣言した場所 | static の有無 | スコープ | 生存期間
関数外 |  | プログラム全体 | プログラム実行中
関数外 | static | ファイル全体 | プログラム実行中
関数内 |  | 関数内 | 関数実行中
関数内 | static | 関数内 | プログラム実行中

関数外で宣言した非 static 変数を広域変数 (グローバル変数) と呼び、関数内で宣言した変数を局所変数 (ローカル変数) と呼びます。広域変数は、複数のファイルで共有されます。

関数内のさらにブロック ({...}) 内で変数を宣言すると、変数のスコープはそのブロック内に限定されます。

参照 静的関数

Copyright © Tama Software Ltd, 1999-2010. ← → 目次 索引


関数

C 言語のソース コードは主に関数 (function) の集まりです。言語によっては「サブルーチン」、「プロシージャ」、「手続き」などの概念がありますが、それらは C ではすべて「関数」です。関数宣言・関数定義の主な構文は次のとおりです。
構文 | type name( [args]... ) { statements... } | // 関数定義
 | type name( [args]... ); | // 関数プロトタイプ宣言

参照 宣言

関数定義

C の実行コードはすべて関数定義の { } 内に記述します。
例 | void func1() { | // 何もしない関数
 | }
 | int func2() { | // int 型の戻り値 3 を返す関数
 | return 3;
 | }
 | int func3() { | // 1 から 10 までの合計を返す関数
 | int i, r;
 | for ( i = 1; i <= 10; i++ )
 | r += i;
 | return r;
 | }

関数の中には任意の実行コード (たとえば代入、加減算、ループなど) を記述します。別の関数を呼び出すこともできます。ただし関数の中で別の関数を定義することはできません。

プロトタイプ宣言

関数本体 ({...} の部分) の定義を持たない関数宣言を「関数プロトタイプ宣言」と呼びます。プロトタイプ宣言を行うと、以降のその関数の定義や呼び出しの型がチェックされ、矛盾があると警告が表示されます。複数のソース ファイルでプログラムを作成する場合は、ヘッダー ファイルに各関数のプロトタイプ宣言を記述しておき、定義と呼び出しの間に型の矛盾がないかチェックすることがよくあります。

プロトタイプ宣言がなくても、関数の定義または呼び出しが行われた時点で、その形式に基づいて関数の型が仮定されます。それ以降、その関数が仮定と異なる型で使用されると、警告が表示されます。

関数の戻り値の型を省略すると、既定で int と仮定されます。戻り値のない関数を宣言・定義するには、戻り値の型を void と指定します。
例 | void func1( void ); | // 関数プロトタイプ宣言。戻り値なし、引数なし
 | int func2( float ); | // 関数プロトタイプ宣言。戻り値 int、引数 float
 | void main() { | // 関数定義
 | int a = func1(); | // 警告。戻り値はないはず
 | int b = func2( 3.14 ); | // 有効
 | func1( a ); | // 警告。引数はないはず
 | func2( a ); | // 有効。a が float に変換される
 | }

関数呼び出し

定義した関数は「<関数名>()」という式で呼び出すことができます。引数がある場合は () の中にカンマ (,) で区切って記述します。関数呼び出しの引数の数と型は、その関数の実際の定義に一致する必要があります。名前は一致しなくてかまいません。
例 | func(); | // func を呼び出す
 | a = func(); | // func を呼び出して戻り値を a に代入
 | a = func( b, c ); | // func を引数 b と c で呼び出して戻り値を a に代入

引数のスコープ

関数の引数のスコープと生存期間は、局所変数と同様に、関数内に限定されます。また、関数内で引数の値を変更しても、その変更は関数呼び出し側のコードには反映されません。ただし、引数がポインタの場合、そのポイント先の値の変更は、関数呼び出し側にも影響します。
例 | void sub( int a, int* b ) {
 | a++;
 | (*b)++;
 | }
 | void func() {
 | int x = 0, y = 0;
 | sub( a, &b ); | // a の値は変化しないが b の値は 1 増える
 | }

return 文と戻り値

return 文が実行されると、コード実行は関数呼び出し (の次の文) に戻ります。
例 | void func( int f ) {
 | if ( f < 0 )
 | return; | // f が負なら関数 func をここで終了
 | ...
 | }

関数からは最大 1 つの値を戻り値 (返り値) として返すことができます。戻り値を指定する場合は、return 文を次のように記述します。
構文 return <式>
例 | return 3; | // 3 を返す
 | return( 3 ); | // 上と同じ
 | return a + b; | // a + b の計算結果を返す

C 言語では関数から複数の値を返すことはできません。関数から複数の値を返したい場合は、一般に次のようにします。

  • ポインタを引数として受け取って、そのポイント先に値を代入する
  • 広域変数に値を代入する
  • 複数の値を構造体にまとめて返す

main 関数

構文 int main( int argc, char* argv[] );

プログラムの実行は main 関数から始まります。

一般に main 関数はスタートアップ ルーチンから呼び出され、main 関数の戻り値はプログラムの終了コードになります。

argc には、コマンドラインで指定したパラメータの数 + 1 が渡されます。パラメータを 1 つも指定しないと、1 が渡されます。

argv には、パラメータ文字列の配列が渡されます。通常、argv[0] には実行したプログラム自体のパスが入りますが、本コンパイラでは常に "(pgm-name)" になります。argv[1] ～ argv[argc-1] にパラメータ文字列が格納され、argv[argc] に NULL が格納されます。

MS-DOS のコマンドライン (または Windows のコマンド プロンプト) では、パラメータをスペースで区切って指定します。パラメータにスペース文字を含めるには、パラメータを " " で囲みます。パラメータに「"」自体を含めるには、" " の中で "" と記述します。
例 | mypgm abc "d e f" """gh""" """"
 | ↓
 | argc = 5
 | argv[0] =「(pgm-name)」
 | argv[1] =「abc」
 | argv[2] =「d e f」
 | argv[3] =「"gh"」
 | argv[4] =「"」
 | argv[5] = NULL

引数の省略記号 (...)

引数の数が不明な場合に使用します。ただし最初の引数には指定できません。
例 | int printf( char*, ... ); | // 2 番目以降の引数の型と数は不明
 | int printf2( ... ); | // これはエラー

va_arg も参照してください。

静的関数

関数の宣言または定義の先頭にキーワード static を付けると、その関数はファイル外に公開されません (つまり別のファイルから使用できなくなります)。言い換えると、キーワード static によってスコープがファイル内に限定された局所的な関数を定義できます。同じ名前の関数が複数のファイルで定義されていると、それらの関数が静的でなければリンク時にエラーになりますが、それらの関数が静的であればエラーになりません。

単一の翻訳単位 (ソース ファイル) からなるプログラムでは、関数が静的かどうかは意味を持ちません。
例 static void local_func();

関数へのポインタ

関数へのポインタを定義できます。
例 | #include <string.h>
 | int (*pf)( const char*, const char* ); | // 関数へのポインタの型 pf を宣言
 | pf = strcmp; | // 関数のアドレスを代入
 | int a = pf( "1", "2" ); | // 関数へのポインタを使って strcmp を呼び出す
 | int b = (*pf)( "1", "2" ); | // 上と同じ意味

ポインタに代入する関数の型が一致しないと、警告が表示されます。
pf = memcpy; // 警告が発生


型

型 (type) は変数の種類を示します。C の変数は必ず型を持ちます。整数または小数を表すいくつかの基本型があり、さらにそこから派生するポインタ、配列などの派生型があります。「変数の宣言」も参照してください。

基本型

表記 | バイト | 符号 | 備考
char | 1 | 有 | 符号の有無は -j で変更可能
signed char | 1 | 有 | 既定では char と同じ
unsigned char | 1 | 無 |
short | 2 | 有 |
signed short | 2 | 有 | short と同じ
unsigned short | 2 | 無 |
int | 2 | 有 |
signed | 2 | 有 | int と同じ
signed int | 2 | 有 | int と同じ
unsigned | 2 | 無 |
unsigned int | 2 | 無 | unsigned と同じ
long | 4 | 有 |
signed long | 4 | 有 | long と同じ
unsigned long | 4 | 無 |
float | 4 | 有 | 浮動小数点数
double | 8 | 有 | 浮動小数点数
long double | 8 | 有 | 浮動小数点数。Light C では double と同じ
void | - | - | 不定または不在を表す。void* p はポイント先の型が不定のポインタを表し、void f() は戻り値のない関数を表します。

派生型

  • ポインタ
  • 配列
  • 構造体
  • 共用体
  • 列挙
  • 関数

ヘッダー ファイルで typedef を使って定義されている型

表記 | 定義ト | ファイル | 備考
size_t | unsigned int | stddef.h | 長さ
wchar_t | unsigned short int | stddef.h |
ptrdiff_t | int | stddef.h | ポインタの差
fpos_t | long | stdio.h | ファイル内の位置
div_t | (構造体) | stdlib.h | div() で使用
ldiv_t | (構造体) | stdlib.h | ldiv() で使用
clock_t | long | time.h | Light C ではミリ秒を表し、clock() で使用される
time_t | long | time.h | Light C では GMT 1970/1/1 からの経過秒数を表し、time() などで使用される
tm | (構造体) | time.h | 時間を表し、mktime() などで使用される
sig_atomic_t | int | signal.h | 単一のマシン命令で読み書きされることが保証される型
jmp_buf | (構造体の配列) | setjmp.h | setjmp() で使用
REGS | (共用体) | dos.h | プロセッサのレジスタを表し、int86() などで使用される
SREGS | (構造体) | dos.h | セグメント レジスタを表し、int86x() などで使用される


記憶クラス

記憶クラス (storage class) は、変数や関数を配置する場所に影響します。各変数または関数につき、次の記憶クラスを最大 1 つ指定できます。

記憶クラス | 説明
auto | 自動変数
extern | 外部参照
static | 静的変数、またはファイル内関数
register | レジスタ変数
typedef | 型定義

auto

局所変数の既定の記憶クラスです。局所変数には暗黙で指定され、局所変数以外には指定できないため、あまり使用されません。
例 | void func() {
 | auto int r = 3; | // 単に「int r = 3;」でも同じ
 | return 3;
 | }

extern

広域変数または関数が別のファイルで定義されていることを示します。
例 | extern int gvar; | // 外部変数宣言
 | extern int func( char* ); | // 外部関数宣言
 | int func( char* ); | // 上と同じ

関数宣言では extern を省略しても同じ結果になります。

実際にその変数または関数が他ファイルで定義されていないと、リンク時にエラーになります。また、実際の定義と extern 宣言の型が一致していないと、不測の結果になります。

static

このキーワードには次の 2 つの役割があります。

  • 広域変数または関数宣言に指定すると、その名前はファイル外に公開されません。
  • 局所変数に指定すると、その変数の値は静的に確保され、関数が終わっても破棄されません。
例 | static int lvar; | // ファイル内でのみ有効な変数
 | static int func( char* ); | // ファイル内でのみ有効な関数
 | int counter() { | // 呼び出された回数を返す関数
 | static int c = 0; | // これを static にしないと毎回 0 にリセットされてしまう
 | return ++c;
 | }

register

int と同じサイズの局所変数 (int、short、unsigned int、near ポインタなど) に register を指定すると、その変数は、スタックではなくレジスタ si または di に置かれます。char、long、float、double、far ポインタ、配列などをレジスタ変数に割り当てることはできません。レジスタ変数は、同時に 2 つまで使用できます。

これにより、変数へのアクセスが高速になります。頻繁に使用する変数、特にポインタに指定すると効果があります。

-o または -or を指定すると、register を記述しなくても、コンパイラの判断で自動的にレジスタ変数が使用されます。ただし、この場合でも明示的な register 指定が優先されます。

typedef

typedef は型を定義する特別なキーワードです。定義した型名は、通常の型名 (int, char* など) と同じように使用できます。

typedef unsigned int uint;
uint x; // unsigned int x と同じ

typedef で定義した型名を使用して、さらに別の名前を定義することもできます。

typedef unsigned int uint;
typedef uint* puint;
puint p; // unsigned int* p と同じ

定義内容が矛盾しない限り、同じ名前を typedef で複数回定義できます。[LC]

typedef unsigned int uint;
typedef unsigned int uint; | // 可
typedef unsigned long uint; | // エラー

ただし、次の定義はエラーになります。

typedef unsigned uint;
typedef unsigned uint;

これは、unsigned だけでは型が完結しないためです。typedef 定義名を再定義する場合は、unsigned int などの完全な型名を使用してください。

_noreg [LC]

このクラスを指定された局所変数は、レジスタに割り付けられず、必ずスタック上に領域が確保されます。

inline [LC]

関数に対して指定する記憶クラスです。インライン関数を定義します。
例 inline int max( int a, int b ) { return a >= b ? a : b; }

インライン関数を呼び出すと、関数呼び出しコードが生成される代わりに、呼び出しの位置に関数のコードが埋め込まれます。このため、コード サイズは増大する可能性がありますが、関数呼び出しが高速になります。

一般に、高速に実行したい小さな関数をインライン関数に指定します。呼び出す前に同一のソース ファイルまたはヘッダー ファイルで定義されている必要があります。


型修飾子

型修飾子 (type qualifier) は、変数の属性を指定します。

型修飾子 | 説明
const | 定数であることを示す
volatile | この変数は自動的に変化する可能性がある
far, _far | far メモリに置かれることを示す (非 ISO/JIS/ANSI)
near, _near | near メモリに置かれることを示す (非 ISO/JIS/ANSI)

const

データを変更できないことを示します。この属性を指定した変数の値を変更しようとすると、エラーになります。

const int i = 1; | // 初期化は可能
int const i2 = 1; | // こう書いても同じ
i = 2; | // エラー
char* const p = "A"; | // 変更できないポインタ
const char* p2 = "A"; | // 変更できないデータへのポインタ
char const* p3 = "A"; | // 同上
p[0] = 0; | // 有効
p2[0] = 0; | // エラー
p = NULL; | // エラー
p2 = NULL; | // 有効

volatile

たとえば入力ポートを指す変数など、自動的に変化する可能性がある特殊な変数に対して指定します。これにより、変数値の不変性を前提とした最適化が抑止されます。volatile 変数はレジスタ変数にはなりません。

far と near

8086 系の 16 ビット システムでは、セグメント レジスタに関連して、ポインタ (アドレス) に far と near の区別があります。「メモリ モデル」も参照してください。

次は、near モデルでの例です。

int i1[100]; | // near メモリに置かれる
int near i2[100]; | // near メモリに置かれる
int far i3[100]; | // far メモリに置かれる
far int i4[100]; | // far メモリに置かれる
void far func() { } | // far メモリに置かれるコード
int* p1; | // near メモリに置かれる near ポインタ
int far* p2; | // near メモリに置かれる far ポインタ
far int* p3; | // 同上
int* far p4; | // far メモリに置かれる near ポインタ
int far* far p5; | // far メモリに置かれる far ポインタ
int far** p6; | // far ポインタへの near ポインタ (near メモリ上)
int* far* p7; | // near ポインタへの far ポインタ (near メモリ上)

near ポインタは 2 バイトで高速ですが、near メモリにあるデータしか指すことができません。far ポインタは 4 バイトで低速ですが、near メモリにあるデータと、far メモリにあるデータの両方を指すことができます。

syscall、stdcall、pascal

関数専用です。「関数呼び出し規約」を参照してください。

interrupt

関数専用です。「割り込みハンドラ」を参照してください。


ポインタ

ポインタ (pointer) は他の変数のアドレスを格納するための 2 バイト (near) または 4 バイト (far) の派生型で、演算子「*」を使って宣言します。
構文 * type
例 | int a = 1;
 | int* ptr = &a; | // ptr ← a のアドレス
 | int b = *ptr; | // b ← ptr のポイント先 ＝ a の値
 | int** pp = &ptr; | // pp ← ptr のアドレス
 | int c = **pp; | // c ← pp のポイント先のポイント先 ＝ a の値

ポインタの値は加減算を行うことができます。1 を加減算すると、ポイント先の型のサイズだけ値が増減するので注意してください。
例 | void func ( char* ptr1, long* ptr2 ) {
 | ptr1++; | // ptr1 の値が 1 増える
 | ptr2++; | // ptr2 の値が 4 増える
 | ptr1 += 10; | // ptr1 の値が 10 増える
 | ptr2 += 10; | // ptr2 の値が 40 増える
 | }

以下にさまざまな例を示します。
例 | char* ptr; | // char データを指すポインタ
 | int* ptr2; | // int データを指すポインタ
 | char a[10];
 | ptr = a; | // 有効
 | ptr2 = a; | // ポイント先の型が違うため、警告される
 | char** ptr3; | // ポインタを指すポインタ
 | char* ptr4[10]; | // ポインタの配列 (10 個の char* ポインタ)
 | char (*ptr5)[10]; | // 配列へのポインタ
 | char* p1;
 | p1++; | // 1 増加
 | short* p2;
 | short* p2b = p2;
 | p2++; | // 2 増加
 | p2 += 3; | // 3 * sizeof(short) = 6 増加
 | int d = p2 - p2b; | // d = 8 / sizeof(short) = 4
 | void (*func)( int ); | // 関数へのポインタ
 | (*func)( 12 ); | // ポインタを介した関数呼び出し
 | func( 12 ); | // こう書いても同じ


配列

配列 (array) は同じ型の変数を複数個並べるための派生型です。
構文 | type name[num];
 | type name[n1][n2]; | // 2 次元配列の宣言
 | type name[n1][n2][n3]; | // 3 次元配列の宣言

宣言と初期化

配列は演算子「[ ]」を使って宣言します。
例 | char a[10]; | // char 要素 10 個の配列 (10 バイト)
 | short b[10]; | // short 要素 10 個の配列 (20 バイト)
 | char c[3][4]; | // char[4] が 3 つ (12 バイト)
 | char* d1[4] | // char を指すポインタが 4 つ
 | char (*d2)[4]; | // char[4] を指すポインタが 1 つ
 | far char [100]; | // far メモリに置かれる
 | char e1[2][3] = {{1,2,3},{4,5,6}}; | // 2 次元配列の初期化
 | char e2[2][3] = {1,2,3,4,5,6}; | // 上と同じ

配列は、文字列リテラルまたは値リスト ({ } で囲んだ初期化子の並び) で初期化できます。char (または wchar_t) と互換性のある型を要素とする配列は、文字列で初期化できます。
例 | char a[4] = "123"; | // 文字列で初期化
 | char b[4] = { 1, 2, 3, 0 }; | // 上と同じ
 | int c[10] = "123"; | // 要素が int 型なのでエラー
 | wchar_t d[3] = L"あか"; | // ワイド文字列で初期化

指定した配列の要素数より初期化子が少ない場合は、残りの領域に 0 が補充されます。
例 char f[5] = "12"; // 0x31,0x32,0,0,0

文字列リテラルで初期化した場合は、余裕があれば末尾に 0 が付加されます。
例 | char a[] = "123"; | // a ← 0x31,0x32,0x33,0 (4 バイト)
 | char a[5] = "123"; | // a ← 0x31,0x32,0x33,0,0 (5 バイト)
 | char a[4] = "123"; | // a ← 0x31,0x32,0x33,0 (4 バイト)
 | char a[3] = "123"; | // a ← 0x31,0x32,0x33 (3 バイト)
 | char a[2] = "123"; | // エラー

初期化子がある場合は、配列の要素数を省略できます。
例 | char f[] = "123"; | // 初期化子があるため要素数は省略可
 | int s1 = sizeof( f ); | // s1 = 4
 | char g[]; | // 初期化子がないためエラー
 | char h[][3] = { "1", "23"}; | // 有効 (2 × 3 = 6 バイト)
 | char i[2][] = { "1", "23"}; | // エラー (最初の次元のみ省略可能)

自動変数の配列に初期化子を指定すると、その配列は静的変数と見なされます。
例 | func() {
 | char a[] = "123"; | // 「static char a[] = "123";」と同じ
 | }

配列の参照

配列の要素は「<配列名>[<要素番号>]」の形式で参照します。先頭要素の番号は 1 ではなく 0 です。また、<配列名> を配列の先頭アドレスを表すポインタとして使用することもできます。
例 | int a[10];
 | int x = a[2]; | // x ← 配列の 2 番目の要素
 | int* p = a; | // p ← 配列の先頭アドレス

関数の引数での配列

関数の仮引数を配列型で宣言した場合、その名前はポインタと同じように扱われます。
例 | void func( int* a ) { ... }
 | void func( int a[] ) { ... } | // 上と同じ
 | void func( int a[10] ) { ... } | // 上と同じ。要素数は無視される

関数の実引数に配列名を渡すと、関数には配列のアドレスがポインタとして渡ってきます。
例 | char a[10];
 | char* p = a;
 | func( a ); | // func に a のアドレスを渡す
 | func( p ); | // 上と同じ結果になる

Light C では、1 つの配列の大きさは 64 KB 以下に制限されています。


構造体

構造体 (structure) は値の集まりです。
構文 | struct tag { declarations... }; | // タグ宣言
 | struct tag { declarations... } name; | // タグ宣言と変数宣言
 | struct { declarations... } name; | // 変数宣言 (無名構造体)
 | struct tag name; | // 変数宣言

タグ宣言と変数宣言

構造体タグを宣言してから、そのタグを使って構造体変数を宣言します。
struct stag { int i; char* p; }; | // タグ宣言
struct stag s1; | // 変数宣言

構造体タグと構造体変数を同時に宣言することもできます。
struct stag { int i; char* p; } s1; // タグ宣言 + 変数宣言

タグを使用しないで「無名構造体 (アノニマス構造体)」を宣言することもできます。
struct { int i; char* p; } s1; // 変数宣言

struct キーワードを省略できるように、typedef が使用されることもよくあります。標準ライブラリの FILE 構造体はその一例です。
typedef struct { int i; char* p; } styp; | // 型宣言
styp s2; | // 変数宣言 (無名構造体)

構造体は入れ子にできます。
struct { int i; char* p; } stag1;
struct stag2 { struct stag1 a; struct stag1 b; }; | // タグ宣言
struct stag2 ns1; | // 変数宣言
struct stag2 ns2 = { {1,"a"}, {2,"b"} }; | // 変数宣言 + 初期化
struct stag2 ns3 = {1,"a",2,"b"}; | // 上と同じ

初期化

値リスト ({ } で囲んだ初期化子の並び) で初期値を指定できます。
struct stag { int i; char* p; } s1; | // タグ宣言
struct stag s1 = { 12, "str" }; | // 変数宣言 + 初期化
struct stag { int i; char* p; } s2 = { 12, "str" }; | // タグ宣言 + 変数宣言 + 初期化

自動変数の構造体に初期化子を指定すると、配列と同様に、その構造体は静的変数と見なされます。

参照

メンバの参照

構造体のメンバを参照するには、メンバ参照演算子「.」を使用します。
struct { int i; char* p; } s1;
int i = s1.i;
char* p = s1.p;

構造体へのポインタからメンバを参照するには、メンバ間接参照演算子「->」を使用します。
struct stag { int i; char* p; } s1;
struct stag* ptr = &s1; | // ptr は構造体へのポインタ
int i2 = ptr->i;
char* p2 = ptr->p;
char* p2a = (*s1).p; | // 上と同じ

代入

構造体は、= 演算子で丸ごと代入 (コピー) できます。
struct stag { int i; char* p; } s1;
struct stag s3 = s1; | // 構造体全体を代入
struct stag* ptr = &s1;
s3 = *ptr; | // 構造体全体を代入

構造体を他の関数に渡す

関数の引数として構造体を受け取ったり、関数から戻り値として構造体を返すことができます。
struct stag { int i; char* p; };
struct stag func( struct stag arg ) {
arg.i += 10;
return( arg );
}

構造体そのものを渡す代わりに、構造体のアドレス (ポインタ) を受け渡すこともできます。構造体のサイズが大きい場合は、この方が高速です。ただし、構造体そのものを渡した場合とは異なり、ポインタで受け取った構造体の内容を変更すると呼び出し側でのその構造体の値も変化します。
struct stag* func( struct stag* arg ) {
return( arg );
}


ビット フィールド

構造体のメンバをビット単位で指定して、領域を節約することができます。
struct tag {
short a:3; | // 3 ビットのフィールド
short b:4; | // 4 ビットのフィールド
short c:5; | // 5 ビットのフィールド
short d:6; | // 6 ビットのフィールド
};

各メンバの型には int、short、char を指定します (ただし、ISO/JIS/ANSI で規定されているデータ型は int のみ)。signed または unsigned を付加することもできますが、その指定にかかわりなく、Light C のビット フィールドは、常に符号なし型として扱われます。

Light C では、各ビット フィールドは下位ビットから詰め込まれます。

上の例では、a、b、c の 3 つのビット フィールドが short の 16 ビット中の下位 12 ビットに詰め込まれ、a が最下位、c が最上位に置かれます。4 番目の d は同じ 16 ビットには収まらないため、次の short に格納されます。この結果、フィールドは次のように配置されます。

変数 | bit15 ← ... → bit0
第 1 の short | ????cccc cbbbbaaa
第 2 の short | ???????? ??dddddd

ビット フィールドは、通常の整数と同じように、加減乗除やビット演算に使用できます。ただし、& 演算子でアドレスを取得したり、sizeof 演算子でサイズを取得することはできません。

通常のメンバと同じように、ビット フィールドも値リストで初期化できます。
struct {
char a:3;
char b:1;
} s = { 3, 1 };


共用体

共用体 (union) は複数の変数を同一のアドレスに重ねて配置するための機能で、struct の代わりに union と記述することを除き、構文は構造体と同じです。
union tag {
long a;
short b;
char c;
};

最も大きいメンバのサイズが、共用体のサイズになります。上の例では long の 4、次の例では short [3] の 6 が共用体のサイズになります。
union tag2 {
long a;
short b[3];
char c[4];
};

共用体は、主に次の目的で使用されます。

  • 同時に使用しないデータを同じアドレスに配置してメモリを節約する。
  • 同じビット データを意図的に別の型として操作する。たとえば、long 変数の各バイトを char 配列として操作する。


列挙

列挙 (enumeration) は連続する整数に名前を付けるための機能です。
構文 | enum [tag] { names,... } [vars],... ;
 | enum tag vars,... ;
 | ※ここで names は name[=value]

names で定義した個々の列挙名には、0 から順番に整数が割り当てられます。
enum { a, b, c }; // a=0, b=1, c=2

これらの列挙名は、プログラム中で整数定数と同じように使用できます。
if ( x == b ) ...;
switch ( x ) {
case a: ...;
case b: ...;
case c: ...;
}

列挙名の値を = で明示的に指定することもできます。その場合は、後続の列挙名の値も影響を受けます。
enum { a, b, c=10, d, e }; // a=0, b=1, c=10, d=11, e=12

複数の列挙名に同じ値を割り当てることもできます。
enum { a, b, c=0, d, e }; // a=0, b=1, c=0, d=1, e=2

列挙型の変数を定義できます。列挙型は int 型と同じものと見なされます。ただし、-wenum を指定した場合は、他の型への変換が警告されます。
enum { a, b, c } e; | // int 型と同じサイズの変数 e を定義
e = a; | // 有効
int i = e; | // 有効
e = i; | // -wenum:1 なら警告
enum { ax, ay, az }; | // ax=0, ay=1, az=2
enum { bx=1, by, bz }; | // bx=1, by=2, bz=3
enum { cx, cy=0, cz }; | // cx=0, cy=0, cz=1
enum { dx, dy } e1; | // dx,dy と列挙型変数 e1 を定義
enum tag { ex, ey }; | // ex,ey と列挙タグ tag を定義
enum tag e2, e2b; | // tag 型で e2 と e2b を定義
e1 = dx; | // 有効
e1 = ex; | // -wenum:1 なら警告
int i = dx; | // 有効
e1 = i; | // -wenum:1 なら警告
e1 = e2; | // -wenum:1 なら警告
e2 = e2b; | // 有効


式と演算子

C 言語の式 (expression) は、名前 (変数名、関数名)、定数リテラル (整数、小数、文字、文字列)、値リスト、またはそれらを演算子 (operator) で結合したものです。
例 | a = 3 | // 二項演算子「=」を使った代入式
 | a += 3 | // 二項演算子「+=」を使った加算式
 | a = b + c | // a = ... と b + c の 2 つの二項演算が入れ子になった式
 | a < b | // 比較式
 | a && b | // 論理式

次の表は、すべての演算子の一覧です。

演算子 | 種類 | 優先 順位 | 結合 | 評価 | 対象 | 説明
(args...) | 右単項 | 1 | → | (N/A) | 関数ポインタ | 関数
[n] | 右単項 | 1 | → | (N/A) | ポインタ/配列 | 配列
. | 二項 | 1 | → | (N/A) | 左：構造体 右項：メンバ名 | 構造体メンバの参照
-> | 二項 | 1 | → | (N/A) | 左：構造体 右項：メンバ名 | 構造体へのポインタからメンバへの参照
var++ var-- | 右単項 | 1 | → | (N/A) | 整数、ポインタ | 後置インクリメント、後置デクリメント
- | 左単項 | 2 | ← | (N/A) | 整数、小数 | マイナス化
! ~ | 左単項 | 2 | ← | (N/A) | 整数 | 論理否定、ビット反転
* | 左単項 | 2 | ← | (N/A) | ポインタ/配列 | ポイント先
& | 左単項 | 2 | ← | (N/A) | 変数 | アドレス
++var --var | 左単項 | 2 | ← | (N/A) | 整数、小数 ポインタ | 前置インクリメント、前置デクリメント
(type) | 左単項 | 2 | ← | (N/A) | 任意 | キャスト
sizeof | 左単項 | 3 | ← | (N/A) | 変数、文字列 | 変数または型のサイズの取得
* / | 二項 | 4 | → | (←) | 整数、小数 | 乗算、除算
% | 二項 | 4 | → | (←) | 整数 | 剰余
+ - | 二項 | 5 | → | (←) | 整数、小数 ポインタ/配列 | 加算、減算
<< >> | 二項 | 6 | → | (←) | 整数 | 左シフト、右シフト
< <= > >= | 二項 | 7 | → | (←) | 整数、小数 ポインタ/配列 | 未満、以下、より大きい、以上
== != | 二項 | 8 | → | (←) | 整数、小数 ポインタ/配列 | 等しい、等しくない
& | 二項 | 9 | → | (←) | 整数 | ビットごとの論理積 (AND)
^ | 二項 | 10 | → | (←) | 整数 | ビットごとの排他的論理和 (XOR)
| | 二項 | 11 | → | (←) | 整数 | ビットごとの論理和 (OR)
&& | 二項 | 12 | → | → | 整数 | 論理積 (AND)
|| | 二項 | 13 | → | → | 整数 | 論理和 (OR)
e1 ? e2 : e3 | 三項 | 14 | ← | → | 左：整数 中,右：任意 | 三項演算 (条件演算)
= | 二項 | 15 | ← | (←) | 左：変数 右：任意 | 代入
+= -= | 二項 | 15 | ← | (←) | 左：変数 右：整数、小数、 ポインタ | 自己演算
*= /= | 二項 | 15 | ← | (←) | 左：変数 右：整数、小数 | 自己演算
%= <<= >>= &= ^= |= | 二項 | 15 | ← | (←) | 左：変数 右：整数 | 自己演算
, | 二項 | 16 | → | → | 任意 | 順次演算 (カンマ演算子)

種類
引数の取り方を示します。次のいずれかの形式です。
  • 右単項 － op arg
  • 左単項 － arg op
  • 二項 － arg1 op arg2
  • 三項 － arg1 op1 arg2 op2 arg3

※arg は引数、op は演算子を示します。

優先順位
演算子の優先順位 (結合力の強さ) を示します。1 が最高です。たとえば * の優先順位は + より高いので、1+2*3 では 2*3 が先に評価されます。

結合の優先順位は ( ) を使って明示的に変更できます。たとえば (1+2)*3 では 1+2 が先に評価されます。( ) および [ ] の中身は最優先で結合します。

結合
オペランドの結合方向を示します。たとえば + 演算子の結合方向は左から右 (→) なので、「a+b+c」は「(a+b)+c」と評価されます。= 演算子の結合方向は右から左 (←) なので、「a=b=c」は「a=(b=c)」と評価されます。
評価
二項以上の演算子で、どちらのオペランドから先に値が計算されるかを示します。たとえば && 演算子の評価方向は左から右 (→) なので、「(a() && b()」では a() より b() が先に計算されます。

結合方向とは異なり、多くの演算子のオペランドの評価順序は、ISO/JIS/ANSI 規格では定められていません。ISO/JIS/ANSI では、上の「評価」欄の矢印に ( ) が付いている演算の評価順序を定めていません。これらの演算については、オプションで評価順序を変更できます。-evall を指定すると「(←)」と記された演算も左オペランドから先に評価されます。

対象
演算子が受け取るオペランドの種類を示します。

各演算子についての説明

演算子 | 説明
[n] | 配列の n-1 番目の要素に評価されます。最初の要素なら 0 を指定します。
+ 整数や小数を加算できるほか、ポインタと整数を加算することができます。その結果はポインタ型になります。ポインタに 1 を足すと、ポインタの値はポイント先のサイズだけ増加します。
例 | long* func( long* p ) {
 | return p + 3; | // p の実際の値に 3 * 4 = 12 を加えた値
 | }
- 整数や小数を減算できるほか、ポインタ同士を減算できます。その結果は int 型になります。ポインタの減算結果は、実際のアドレス値の差をポイント先のサイズで割った値になります。
例 | char* p1 = x;
 | char* p2 = p1 + 12;
 | int dif = (long*)p2 - (long*)p1; | // 結果は 12 ではなく 12 / 4 = 3
% a % b は a を b で割ったときの剰余 (余り) を返します。この演算子は整数に適用します。小数の剰余は fmod 関数で取得できます。
<< >> a << b は a の各ビットを b 個だけ左にシフトします。右端のビットには 0 が入ります。a >> b は同様に右シフトします。符号付き値を右シフトした場合、最上位ビット (符号ビット) はシフトされずに残ります。
< <= > >= == != これらの比較演算子は、整数、浮動小数点数、ポインタに適用され、条件が成立した場合は 1、そうでない場合は 0 に評価されます。
~ & ^ | これらのビット演算子は、整数に適用され、個々のビットの論理演算結果を返します。
! && || これらの論理演算子は、整数に適用されます。0 以外に評価されるオペランドを 1、0 に評価されるオペランドを 0 として論理演算した結果を 1 または 0 で返します。
e1 ? e2 : e3 | e1 が成立した場合 (0 以外に評価された場合) は e2 が評価され、そうでない場合は e3 が評価されます。
= 式 a = b は b の値を a に代入し、その値に評価されます。つまり a = b は値を持つ式であり、その上で b を a に代入するという副作用を持っています。

a = b は a + b などと同じように、式を使用できる任意の文脈で使用できます。
例 | a = b = c; | // b = c; a = b; と同じ
 | c += (a = b); | // a = b; c += a; と同じ
 | if ( a = b ) ... | // if ( a == b ) とは異なるので注意

+= -= *= /=
%=
<<= >>=
&= ^= |= 		a += b は a = a + b と同じです。

a <<= b は a = a << b と同じです。

他の演算子も同様です。

, 式 a, b は a と b を順に評価し、b の値を返します。


制御文

次の制御文 (control statement) とラベル (label) を使用できます。

条件分岐

if <条件式 1>
<文またはブロック 1>
else if <条件式 2>
<文またはブロック 2>
else if <条件式 3>
<文またはブロック 3>
...
else
<文またはブロック Z>

<条件式 1> が真であれば、<文またはブロック 1> が実行されます。

<条件式 1> が偽で <条件式 2> が真であれば、<文またはブロック 2> が実行されます。<条件式 1> も <条件式 2> も偽で <条件式 3> が真であれば、<文またはブロック 3> が実行されます。このように else if 節はいくつでも続けられます。

最後に、if 節とすべての else if 節が偽であれば、<文またはブロック Z> が実行されます。

それぞれの <条件式> には整数式を指定します。この整数式が 0 以外に評価されれば真、0 に評価されれば偽と見なされます。

switch (<判定式>) {
case <値 1>:
<文またはブロック 1>...
[break;]
case <値 2>:
<文またはブロック 2>...
[break;]
...
default:
<文またはブロック Z>...
}

<判定式>には int 型の式を指定します。その式の値が <値 1>と等しければ、制御は <文またはブロック 1>の先頭に移動します。式の値が <値 2>と等しければ、制御は <文またはブロック 2>の先頭に移動します。同様の case ラベルをいくつでも記述できます。case に指定する <値>が重複してはなりません。

<判定式>の値がどの case 値にも一致しない場合、制御は default ラベルがあればそこに移動し、default ラベルがなければ最後の}の次に移動します。

break があると、制御は最後の}の次に移動します。

ループ

for (<初期化式>; <条件式>; <更新式>)
<文またはブロック>

  1. 最初に <初期化式> が実行されます。
  2. 次に <条件式> が評価され、偽であれば for ループは終了して制御が <文またはブロック> の次に移動します。
  3. <文またはブロック> が実行されます。
  4. 最後に <更新式> が実行され、制御は手順2 に戻ります。

<文またはブロック> の途中に break または continue 文 (後述) を含めることもできます。

<初期化式>、<条件式>、<更新式> は、いずれも省略可能です。<文またはブロック> は空文 (「;」だけの記述) でもかまいません。
// 0 ～ 9 を表示する
int i;
for ( i = 0; i < 10; i++ )
printf( "i=%d\n", i );

Light C では、<初期化式> で変数を宣言することもできます。
// 上のコード例と同じ
for ( int i = 0; i < 10; i++ )
printf( "i=%d\n", i );

メモ ただし C99 仕様とは異なり、<初期化式> で宣言された変数のスコープは、for 文内にとどまらず、同一関数内の以降の部分すべてに渡ります (過去の C++ の仕様と同じ)。

while (<条件式>)
<文またはブロック>

  1. 最初に <条件式> が評価され、偽であれば while ループは終了して制御が <文またはブロック> の次に移動します。
  2. 次に <文またはブロック> が実行されます。
  3. 制御が手順1 に戻ります。

<文またはブロック> の途中に break または continue 文 (後述) を含めることもできます。

<条件式> は省略できません。常に真にしたい場合は定数の 1 などを指定します。<文またはブロック> は空文 (「;」だけの記述) でもかまいません。

do
<文またはブロック>
while (<条件式>);

  1. 最初に <文またはブロック> が実行されます。
  2. 次に <条件式> が評価され、偽であれば do ループは終了して制御が <文またはブロック> の次に移動します。
  3. 制御が手順1 に戻ります。

その他

break

for、while、do、switch の <文またはブロック> の中に記述します。break 文は、制御を for、while、do、switch の次の文に移動します。

continue

for、while、do の <文またはブロック> の中に記述します。continue 文は、制御をループの先頭に戻します。for の場合、<更新式> は実行されません。

goto <ラベル名>;

下の構文で定義したラベルに制御を移動します。

<ラベル名>:

goto 文のジャンプ先として使用するラベルを定義します。

Light C では、ラベルは変数と同じように { } によるスコープの影響を受けます。


ライブラリ関数

C 言語では標準で多くのライブラリ関数が提供されています。ライブラリ関数を使用するときは、所属するヘッダー ファイルをインクルードすることをお勧めします (そうしないと使用できない関数もあります)。

  • 名前の先頭に下線 (_) が付いていない関数は、ISO/JIS/ANSI 規格に準拠しています。下線が付いている関数は、Light C 独自の拡張です。
  • ISO/JIS/ANSI 規格外でも、_stricmp などのよく使用される関数については、下線のないバージョンが用意されています。これらの関数には、以下の表で「 * 」と付記されています。下線のないバージョンは、-ansi オプションで無効になります。
  • # と記されている関数には、far メモリ版が用意されています。small/medium モデルでは、これらの関数名の先頭に「_f」を付加して、far メモリ版を使用できます。compact/large モデルでは、標準版と far メモリ版が同じ実装になるため、「_f」を付加しても効果はありません。
  • isalpha、labs など、一部の関数はマクロとして実装されています。

オペレーティング システムに依存しない関数

文字列操作

関数 | 所属 | 説明
strcpy # , strncpy | string.h | コピー
memcpy # , memmove # | string.h | コピー
memset # | string.h | 充填
strcat # , strncat | string.h | 連結
strlen # | string.h | 長さの計測
strcmp # , strncmp, memcmp # | string.h | 比較
_stricmp # * , _memicmp # * | string.h | 比較 (大文字と小文字を区別しない)
_strhcmp, _strtcmp | string.h | 先頭および末尾の比較
strchr # , strrchr, memchr # | string.h | 文字の検索
strstr, _memstr | string.h | 文字列の検索
strspn, strcspn, strpbrk | string.h | 文字群の検索
strtok | string.h | トークンの切り出し
_memrep | string.h | 文字列の置換
_memshl | string.h | ビット シフト
_memand, _memor, _memxor, _memnot | string.h | ビット演算 (AND, OR, XOR)

文字列への変換

関数 | 所属 | 説明
sprintf, vsprintf | stdio.h | 書式化
_itoa * | stdlib.h | int → 文字列
_utoa * | stdlib.h | unsigned int → 文字列
_ltoa * | stdlib.h | long → 文字列
_ultoa * | stdlib.h | unsigned long → 文字列

文字列からの変換

関数 | 所属 | 説明
sscanf, vsscanf | stdio.h | 指定の書式に従って解析
atoi | stdlib.h | 文字列 → int
strtol, atol | stdlib.h | 文字列 → long
strtoul | stdlib.h | 文字列 → unsigned long
strtod, atof | stdlib.h | 文字列 → double

文字

関数 | 所属 | 説明
isalnum, isalpha, iscntrl, isdigit, isgraph, islower, isprint, ispunct, isspace, isupper, isxdigit | ctype.h | 文字の分類
isleadbyte, _iskanji * , _iskanji2 * , _iskana * , _iskmoji * | ctype.h | 文字の分類
_iskanji2nd | ctype.h | 全角第 2 バイトかどうかの判定
tolower, toupper | ctype.h | 大文字化、小文字化
_jis2sjis, _sjis2jis | ctype.h | JIS コードと Shift-JIS コードの相互変換

多バイト/ワイド文字

関数 | 所属 | 説明
mblen | string.h | 多バイト文字の文字サイズの取得
mbtowc | stdlib.h | 多バイト文字 → ワイド文字
wctomb | stdlib.h | ワイド文字 → 多バイト文字
mbstowcs | stdlib.h | 多バイト文字列 → ワイド文字列
wcstombs | stdlib.h | ワイド文字列 → 多バイト文字列
wcslen, wcscpy, wcsncpy, wcscat, wcsncat, wcscmp, wcsncmp | string.h | ワイド文字列の各種操作

浮動小数点演算

関数 | 所属 | 説明
fabs | math.h | 絶対値
fmod | math.h | 剰余
sqrt | math.h | 平方根
exp | math.h | 指数関数 ex
pow | math.h | 累乗 yx
log | math.h | 自然対数 logex
log10 | math.h | 常用対数 log10x
sin, cos, tan | math.h | 三角関数
asin, acos, atan, atan2 | math.h | 逆三角関数
sinh, cosh, tanh | math.h | 双曲線関数
floor | math.h | 小数点以下の切り捨て
ceil | math.h | 小数点以下の切り上げ
modf | math.h | 整数部分と小数部分の取得
frexp | math.h | x × 2y に分解
ldexp | math.h | x × 2y から合成
_getfcw, _setfcw | math.h | FPU の丸めモードの取得と設定

時間

関数 | 所属 | 説明
clock | time.h | プログラムの起動からの経過時間の取得
time | time.h | 現在の日時を time_t 型で取得
gmtime | time.h | time_t から tm への変換 (GMT)
localtime | time.h | time_t から tm への変換
mktime | time.h | tm から time_t への変換
ctime | time.h | time_t から文字列への変換
asctime | time.h | tm から文字列への変換
strftime | time.h | 文字列から tm への変換
difftime | time.h | 2 つの日時の差の取得

シグナル

関数 | 所属 | 説明
signal | signal.h | ハンドラ関数の登録
raise | signal.h | ハンドラ関数の呼び出し

longjmp

関数 | 所属 | 説明
setjmp | setjmp.h | ジャンプ先の記憶
longjmp | setjmp.h | ジャンプ実行

プロセッサ/メモリ直接アクセス

関数 | 所属 | 説明
peekw, peekb | dos.h | メモリ直接読み出し
pokew, pokeb | dos.h | メモリ直接書き込み
inportw, inportb | dos.h | I/O ポートから入力
outportw, outportb | dos.h | I/O ポートへ出力
FP_SEG, FP_OFF, MK_FP | dos.h | ポインタとセグメント/オフセットの相互変換
get_regs, get_sregs | dos.h | レジスタ値の取得
set_regs | dos.h | レジスタ値の設定
int86, int86x | dos.h | 割り込みの実行
intdos, intdosx | dos.h | MS-DOS ファンクション コールの実行
getvect | dos.h | 割り込みベクタの取得
setvect | dos.h | 割り込みベクタの設定

その他

関数 | 所属 | 説明
abs, labs | stdlib.h | 絶対値の取得
div, ldiv | stdlib.h | 商と剰余の取得
qsort | stdlib.h | クイック ソート
bsearch | stdlib.h | 二分検索
rand, srand | stdlib.h | 乱数
_max * , _min * | stdlib.h | 大きい方、小さい方の選択 (マクロ関数)
offsetof | stddef.h | 構造体メンバのオフセットの取得 (マクロ関数)
strerror | string.h | エラー メッセージの取得
assert | assert.h | デバッグ目的のチェック
va_start, va_arg, va_end | stdarg.h | 可変個引数の取得
_rest_stack, _min_stack | stdlib.h | 残存スタック サイズの取得
_asmcode | stdlib.h | 機械語コードの直接実行

オペレーティング システムに依存する関数

入出力 [OS]

関数 | 所属 | 説明
fopen | stdio.h | ファイルのオープン
freopen | stdio.h | ファイルの再オープン
fclose | stdio.h | ファイルのクローズ
fflush | stdio.h | ファイル バッファのフラッシュ
fseek, fsetpos, rewind | stdio.h | ファイル ポインタの移動
ftell, fgetpos | stdio.h | ファイル ポインタの位置の取得
feof | stdio.h | ファイル終端の検査
ferror | stdio.h | エラー発生の確認
clearerr | stdio.h | ファイル終端フラグとエラー フラグのリセット
setvbuf, setbuf | stdio.h | ファイル バッファの設定
remove | stdio.h | ファイルの削除
rename | stdio.h | ファイル名の変更
tmpnam | stdio.h | 一時ファイル名の取得
tmpfile | stdio.h | 一時ファイルのオープン

出力

関数 | 所属 | 説明
printf, vprintf | stdio.h | 書式化して出力
puts | stdio.h | 文字列を出力
putchar | stdio.h | 1 バイトを出力
fprintf, vfprintf | stdio.h | 書式化してファイルに出力
fwrite # | stdio.h | 指定長のデータをファイルに出力
fputs # | stdio.h | 文字列をファイルに出力
_putw | stdio.h | 2 バイトをファイルに出力
fputc, putc | stdio.h | 1 バイトをファイルに出力

入力

関数 | 所属 | 説明
scanf, vscanf | stdio.h | 指定の書式に従って入力
gets | stdio.h | 文字列を入力
getchar | stdio.h | 1 バイトを入力
fscanf, vfscanf | stdio.h | 指定の書式に従ってファイルから入力
fread | stdio.h | 指定長のデータをファイルから入力
fgets | stdio.h | 文字列をファイルから入力
_getw | stdio.h | 2 バイトをファイルから入力
fgetc, getc | stdio.h | 1 バイトをファイルから入力
ungetc | stdio.h | 文字入力の取り消し

低水準入出力

関数 | 所属 | 説明
_creat, _open, _close, _read, _lseek | stdio.h | 直接 OS を呼び出す入出力関数

メモリ割り当て [OS]

関数 | 所属 | 説明
malloc, _nmalloc, _fmalloc | malloc.h | メモリの取得
free, _nfree, _ffree | malloc.h | メモリの解放
realloc, calloc | malloc.h | メモリの取得
_msize | malloc.h | メモリ ブロック サイズの取得
_nmrest, _fmrest | malloc.h | 残存メモリ サイズの取得

その他 [OS]

関数 | 所属 | 説明
main |  | 最初に呼び出される関数
exit, _exit | stdlib.h | 終了
atexit | stdlib.h | 終了時に呼び出される関数の登録
abort | stdlib.h | 異常終了
getenv | stdlib.h | 環境変数の値の取得
system, _system | stdlib.h | 他のプログラムの実行
_getpsp | stdlib.h | MS-DOS の PSP の取得
perror | stdio.h | エラー メッセージの表示

変換指定子

入力変換指定子

出力変換指定子

Copyright © Tama Software Ltd, 1999-2010. ← → 目次 索引


文字列操作関数

文字列操作関数 (string.h)

char* strcpy( char* dst, const char* src );
char* strncpy( char* dst, const char* src, size_t len );
char* _fstrcpy( char far* dst, const char far* src );

ヌル終端文字列 src を dst にコピーし、dst を返します。strncpy では、コピーする最大の長さを len で指定できます。コピーが len の制限によって終了したときを除き、dst の末尾には 0 が付加されます。

void* memcpy( void* dst, const void* src, size_t len );
void* memmove( void* dst, const void* src, size_t len );
void* _fmemcpy( void far* dst, const void far* src, size_t len );
void* _fmemmove( void far* dst, const void far* src, size_t len );

src を len バイトだけ dst にコピーします。memmove では、コピー元とコピー先のメモリ範囲が重なっている場合でも、正しくコピーが行われます。

void* memset( void* dst, int chr, size_t len );
void* _fmemset( void far* dst, int chr, size_t len );

chr で示されるバイトを dst 以降の len バイトの範囲にコピーします。

char* strcat( char* dst, const char* src );
char* strncat( char* dst, const char* src, size_t len );
char* _fstrcat( char far* dst, const char far* src );

文字列 src を文字列 dst の末尾に連結し、dst を返します。strncat では、src からコピーする最大の長さを len で指定できます。dst の末尾には、必ず 0 が付加されます。

size_t strlen( const char* str );
size_t _fstrlen( const char far* str );

str の長さを返します。つまり、str 上の最初の 0 までのバイト数を返します。

int strcmp( const char* dst, const char* src );
int strncmp( const char* dst, const char* src, size_t len );
int memcmp( const void* dst, const void* src, size_t len );
int _fstrcmp( const char far* dst, const char far* src );
int _fmemcmp( const void far* dst, const void far* src, size_t len );

dst と src を比較し、一致した場合は 0 を返します。一致しない場合は、最初の相違バイトを比較して、dst の方が大きい場合は 1 を、dst の方が小さい場合は -1 を返します。

strncmp では、比較する最大の長さを len で指定できます。memcmp では、常に len バイト分のメモリが比較されます。

int _stricmp( const char* dst, const char* src );
int _memicmp( const void* dst, const void* src, size_t len );
int _fstricmp( const char far* dst, const char far* src );
int _fmemicmp( const void far* dst, const void far* src, size_t len );

strcmp および memcmp と似ていますが、半角の大文字と小文字を区別しません。全角文字の第 2 バイトが半角英字と同じコードになるときも、正しく処理されます。

int _strhcmp( const char* area, const char* str );

文字列 area の先頭部分が文字列 str と一致した場合は、0 を返します。それ以外の場合は、strcmp と同じ方式で 1 または -1 を返します。

int _strtcmp( const char* area, const char* str );

文字列 area の最後の部分が文字列 str と一致した場合は、0 を返します。それ以外の場合は、0 以外を返します。

char* strchr( const char* area, int chr );
char* strrchr( const char* area, int chr );
void* memchr( const void* area, int chr, size_t len );
char far* _fstrchr( const char far* area, int chr );
void far* _fmemchr( const void far* area, int chr, size_t len );

area からバイト値 chr を検索し、発見した最初のバイトへのポインタを返します。見つからない場合は、NULL を返します。strchr と strrchr は、文字列 area の終端までを検査します。memchr は、常に len バイト分のメモリを検査します。strrchr は area を末尾から検索します。

char* strstr( const char* area, const char* str );
void* _memstr( const void* area, const char* str, size_t len );

文字列 area から文字列 str を検索し、発見した最初の文字列へのポインタを返します。見つからない場合は、NULL を返します。

size_t strspn( const char* area, const char* str );

文字列 area から、str に含まれるいずれかのバイトを検索します。発見した場合は、先頭からそのバイトまでの距離を返します。発見できなかった場合は、area の長さを返します。

size_t strcspn( const char* area, const char* str );

文字列 area から、str に含まれないバイトを検索します。発見した場合は、先頭からそのバイトまでの距離を返します。発見できなかった場合は、area の長さを返します。

char* strpbrk( const char* area, const char* str );

文字列 area から、str に含まれるいずれかのバイトを検索します。発見した場合は、そのバイトへのポインタを返します。発見できなかった場合は、NULL を返します。

char* strtok( char* text, const char* delim );

text をトークンに分割します。文字列 delim で、デリミタ (区切り文字) として使用するバイト群を指定します。text の内容は書き換えられます。

text の先頭にあるデリミタ バイト群を飛ばした後、text 上でトークンとなる範囲の末尾に 0 を書き込み、トークンの先頭を返します。次に、text に NULL を指定してこの関数を呼び出すと、前回切り出したトークンの次のトークンが返されます。
char buf[] = "\t Dear sir,\n";
char* tk = strtok( buf, " \t\n" ); | // tk = "Dear"
tk = strtok( NULL, " \t\n" ); | // tk = "sir,"
tk = strtok( NULL, " \t\n" ); | // tk = NULL

int _memrep( void* area, size_t len, char* sch, char* rep );

len バイトのデータ area に含まれる文字列 sch をすべて文字列 rep に置換し、置換した数を返します。area には、置換後の文字列を格納するための十分な大きさが必要です。

void _memshl( void* mem, size_t len, int count );

len バイトのデータ mem を左に count ビットだけシフトします。右にシフトするには、count に負数を指定します。

void _memand( void* dst, size_t len, const void* src );
void _memor( void* dst, size_t len, const void* src );
void _memxor( void* dst, size_t len, const void* src );

それぞれ dst と src の論理積、論理和、排他的論理和を計算し、結果を dst に格納します。

void _memnot( void* mem, size_t len );

len バイトのデータ mem のビットを反転します。


文字列への変換関数

int sprintf( char* buf, const char* form, ... ); (stdio.h)
int vsprintf( char* buf, const char* form, va_list lst );

データを書式化して buf に書き込みます。form には、出力変換指定子を含む文字列を指定します。また、form 内の % 文字列に対応する変数を form の後に指定します。

原則として、form の文字列がそのまま出力されます。

ただし、form 内に % で始まる部分文字列 (出力変換指定子、"%d" など) を含めると、その部分は form の後に指定した引数に置き換えられます。form は複数の出力変換指定子を含めると、form 後の複数の引数に順番に置き換えられます。form 後の引数の出力形式は、出力変換指定子の文字列で詳細に制御できます。

また、form 内に "\n" などのエスケープ シーケンスを含めると、その部分は実際のコードに置き換えられます。
例 | sprintf( buf, "i=%d\n", i );
 | sprintf( buf, "i=%10.3ld\n", num );

sprintf は vsprintf を使って次のように定義されています。
例 | int sprintf( char* buf, const char* form, ... ) {
 | va_list lst;
 | va_start( lst, form );
 | return( vsprintf( buf, form, lst ) );
 | }

メモ 文字列の長さについては、%d、%f などで生成される個々の数値の文字列表現が 500 バイトを超えてはならないことを除き、制限はありません。

参照 printf、sscanf

char* _itoa( int num, char* str, int base ); (stdlib.h)
char* _utoa( unsigned num, char* str, int base );
char* _ltoa( long num, char* str, int base );
char* _ultoa( unsigned long num, char* str, int base );

数値 num を基数 base で文字列に変換し、str に格納します。str の末尾には 0 が付加され、str が返されます。


文字列からの変換関数

int sscanf( const char* buf, const char* form, ... ); (stdio.h)
int vsscanf( const char* buf, const char* form, va_list lst );

buf で渡された文字列を form に従って解析し、整数、浮動小数点数、文字列などを取得します。form には、入力変換指定子を含む文字列を指定します。また、form 内の % 文字列に対応する変数

    のアドレス
を form の後に指定します。

scanf と fscanf も、入力元の違いを除き、この関数と同じです。sscanf はメモリ データ (buf) を読み取りますが、scanf は標準入から、fscanf は指定されたファイルからデータを読み取ります。scanf と fscanf については、この点だけを読み替えてください。

これらの関数は、入力した変数の個数を返します。エラーが発生した場合、および入力元が空文字列または EOF であったために変数を 1 つも入力できなかった場合は、-1 を返します。

これらの関数では、入力データが form と照合され、一致すれば入力が続行されます。一致しないと、入力はその直前で終了します。入力の終了位置という概念は、sscanf では意味がありませんが、fscanf では、関数終了後の入力ファイルの位置に影響します。

  • form の次の文字がホワイトスペースである場合は、ホワイトスペース以外のバイトが出現するまで、入力データが読み飛ばされます。
  • form の次の文字がホワイトスペースでも % でもない場合は、次の入力データとその文字が比較され、一致しなければ、その直前で入力が終了します。
  • form の次の文字が % の場合は、それ以降の一定範囲が入力変換指定子と見なされます。この場合は、入力データが入力変換指定子に従って解析され、form の後に指定した引数に格納されます。form に複数の入力変換指定子が含まれている場合は、それぞれの解析結果が form 後の複数の引数に順番に格納されます。form に続く引数が不足すると、予測できない結果になります。

form に文字 "%" 自体を含めるには、sprintf と同様に、"%%" と記述します。

form には、エスケープ シーケンスを含めることもできます。
例 | int a; long b; char s[10];
 | sscanf( "12", "%d", &a ); | // a=12
 | sscanf( "12", "%ld", &b ); | // b=12
 | sscanf( "1 2", "%d %ld", &a, &b ); | // a=1, b=2
 | sscanf( "1,2", "%d,%ld", &a, &b ); | // a=1, b=2
 | sscanf( " AB XY", "%s", s ); | // s[]="AB"

メモ 文字列の長さについては、%d、%f などで読み込む個々の数値の文字列表現が 500 バイトを超えてはならないことを除き、制限はありません。

int atoi( const char* str ); (stdlib.h)

文字列を int 整数に変換します。(int)atol( str ) と同じです。

long strtol( const char* str, char **end, int base ); (stdlib.h)
long atol( const char* str );

文字列を long 整数に変換します。文字列先頭のホワイトスペースは読み飛ばされます。

strtol は、次の形式の str を基数 base の文字列と見なして数値に変換します。

[+|-]digits
(digits は 0 ～ 9、A ～ Z、または a ～ z の列)

base に 0 を指定すると、0x または 0X で始まる数値は 16 進数、0 で始まる数値は 8 進数、それ以外の数値は 10 進数と見なされます。

解析は、指定された基数の数値として解釈できない文字が現れた時点で終了します。end に NULL 以外を指定すると、str の解析が終了した位置が *end に格納されます。

数値がオーバーフローした場合は、errno に ERANGE が設定され、符号に応じて LONG_MIN または LONG_MAX が返されます。1 文字も解析できなかった場合は、0 が返されます。

atol は、数値がオーバーフローしても errno が変化しないことを除き、strtol( str, NULL, 10 ) と同じです。

unsigned long strtoul( const char* str, char **end, int base ); (stdlib.h)

文字列を unsigned long 整数に変換します。マイナス (-) 符号を受け付けないこと、および数値の有効範囲が異なることを除き、strtol と同じです。数値がオーバーフローした場合は、ULONG_MAX が返されます。

double strtod( const char* str, char **end ); (stdlib.h)
double atof( const char* str );

文字列を double 値に変換します。文字列先頭のホワイトスペースは読み飛ばされます。

strtod は、次の形式の str を浮動小数点数に変換します。

[+|-]digits[.[digits]][{e|E}[+|-]digits]
(digits は 0 ～ 9 の列)

解析は、指定された基数の数値として解釈できない文字が現れた時点で終了します。end に NULL 以外を指定すると、str の解析が終了した位置が *end に格納されます。

数値がオーバーフローした場合は、errno に ERANGE が設定され、符号に応じて HUGE_VAL または - HUGE_VAL が返されます。1 文字も解析できなかった場合は、0.0 が返されます。

atof は、数値がオーバーフローしても errno が変化しないことを除き、strtod( str, NULL ) と同じです。


文字関数

文字関数 (ctype.h)

is で始まる以下の関数は、特定の種類の文字コードを受け取ったときに 0 以外 (真) を返し、そうでなければ 0 (偽) を返します。

int isalpha( int c );

英字 ('A' ～ 'Z'、'a' ～ 'z') ならば真。

int isupper( int c );

英大文字 ('A' ～ 'Z') ならば真。

int islower( int c );

英小文字 ('a' ～ 'z') ならば真。

int isalnum( int c );

英数字 ('0' ～ '9'、'A' ～ 'Z'、'a' ～ 'z') ならば真。

int isdigit( int c );

数字 ('0' ～ '9') ならば真。

int isxdigit( int c );

16 進数字 ('0' ～ '9'、'A' ～ 'F'、'a' ～ 'f') ならば真。

int isspace( int c );

ホワイトスペース (' '、'\t'、'\r'、'\n'、'\v'、'\f') ならば真。

int isprint( int c );

表示可能文字 (20h ～ 7Eh) ならば真。

int isgraph( int c );

スペースを除く表示可能文字 (21h ～ 7Eh) ならば真。

int iscntrl( int c );

制御文字 (00h ～ 1Fh、7Fh) ならば真。

int ispunct( int c );

デリミタ (21h ～ 2Fh、3Ah ～ 40h、5Bh ～ 60h、7Bh ～ 7Eh) ならば真。

int isleadbyte( int c );
int _iskanji( int c );

Shift-JIS 全角文字の第 1 バイト (81h ～ 9Fh、E0h ～ FCh) ならば真。この 2 つの関数は同じです。

参照 mblen

int _iskanji2( int c );

Shift-JIS 全角文字の第 2 バイトとなり得る文字 (40h ～ 7Eh、80h ～ FCh) ならば真。

int _iskana( int c );

半角カナ文字 (A6h ～ DFh) または半角カナの記号 (A1h ～ A5h) ならば真。

int _iskmoji( int c );

半角カナ文字 (A6h ～ DFh) ならば真。

int _iskanji2nd( char* str, size_t idx );

str から始まる文字列の第 idx バイトが Shift-JIS 全角文字の第 2 バイトかどうかを判定します。str は、半角文字または全角第 1 バイトの位置を指している必要があります。この関数を使用すると、_iskanji2 とは異なり、文脈を考慮しながら確実に全角第 2 バイトを判別できます。

int toupper( int c );
int tolower( int c );

toupper は、半角の英小文字を大文字に変換します。
tolower は、半角の英大文字を小文字に変換します。

wchar_t _jis2sjis( wchar_t jis );
wchar_t _sjis2jis( wchar_t sjis );

_jis2sjis は、JIS コードを Shift-JIS コードに変換します。

_sjis2jis は、Shift-JIS コードを JIS コードに変換します。

JIS コードと Shift-JIS コードは、いずれも wchar_t 型の上位に第 1 バイトを、下位に第 2 バイトを入れて表現します。たとえば、文字「あ」は、JIS では 0x2422、Shift-JIS では 0x82A0 で表されます。
_jis2sjis( 0x2422 ) | // 0x82A0 が返される
_sjis2jis( 0x82A0 ) | // 0x2422 が返される
_sjis2jis( L'あ' ) | // 0x2422 が返される


多バイト/ワイド文字関数

多バイト/ワイド文字関数 (string.h)

int mblen( const char* mbs, size_t mlen );

mbs の先頭文字のバイト サイズを取得します。 この呼び出しは、mbtowc( NULL, mbs, mlen ) と等価です。

参照 _iskanji

int mbtowc( wchar_t* wc, const char* mb, size_t mlen );

多バイト文字 mb をワイド文字に変換し、*wc に書き込みます。ただし、wc が NULL の場合、書き込みは行われません。mlen には、変換する最大バイト数を指定します。

戻り値は、多バイト文字のバイト数です。ただし、mbs が NULL の場合、mlen が 0 の場合、および mbs[0] が 0 の場合は、0 が返されます。

Light C では、_iskanji を使って文字のサイズが判定されます。

int wctomb( char* mb, wchar_t wc );

ワイド文字 wc を多バイト文字に変換し、mb に書き込みます。mb には、最大で MB_CUR_MAX バイトのデータが書き込まれます。MB_CUR_MAX は stdlib.h で定義されており、Light C では 2 です。

戻り値は、mb に書き込まれたバイト数です。ただし、wc が 0 の場合は、mb[0] に 0 が書き込まれますが、0 が返されます。

size_t mbstowcs( wchar_t* wcs, const char* mbs, size_t wlen );

多バイト文字列 mbs をワイド文字列に変換し、wcs に書き込みます。wlen には、wcs で受け取る最大文字数を指定します。

wlen まで書き込むか、mbs[] 上の 0 に到達すると、変換は終了します。後者の場合は、wcs[] の末尾に 0 が書き込まれます。

戻り値は、wcs に書き込まれた文字数です。末尾の 0 は含まれません。

size_t wcstombs( char* mbs, const wchar_t* wcs, size_t mlen );

ワイド文字列 wcs を多バイト文字列に変換し、mbs に書き込みます。mlen には、mbs で受け取る最大バイト数を指定します。

書き込み長が mlen を超えそうになるか、wcs[] 上の 0 に到達すると、変換は終了します。後者の場合は、mbs[] の末尾に 0 が書き込まれます。

戻り値は、mbs に書き込まれたバイト数です。末尾の 0 は含まれません。

size_t wcslen( const wchar_t* src );
wchar_t* wcscpy( wchar_t* dst, const wchar_t* src );
wchar_t* wcsncpy( wchar_t* dst, const wchar_t* src, size_t len );
wchar_t* wcscat( wchar_t* dst, const wchar_t* src );
wchar_t* wcsncat( wchar_t* dst, const wchar_t* src, size_t len );
int wcscmp( const wchar_t* dst, const wchar_t* src );
int wcsncmp( const wchar_t* dst, const wchar_t* src, size_t len );

それぞれ、"wcs" を "str" に読み替えた名前を持つ関数のワイド文字版です。

参照 strlen、strcpy、strncpy、strcat、strncat、strcmp、strncmp


浮動小数点演算関数

浮動小数点演算関数 (math.h)

double fabs( double x );

x の絶対値を取得します。

参照 abs

double fmod( double dvd, double dsr );

dvd を dsr で割ったときの剰余、つまり dvd=dsr*i+rem (i は整数) となるような rem を取得します。dsr の符号は無視され、結果の符号は dvd と同じになります。dsr が 0.0 の場合は、0.0 が返されます。

参照 div、modf、floor

double sqrt( double x );

x の平方根 (ルート) を取得します。x が負の場合は、errno に EDOM が設定され、0.0 が返されます。

double exp( double x );

ネイピア数 (自然対数の底) e の x 乗 (ey) を取得します。e は約 2.718281828 です。結果が大きすぎる場合は、errno に ERANGE が設定され、HUGE_VAL が返されます。

double pow( double x, double y );

x の y 乗 (xy) を取得します。x が 0.0 で y が 0.0 以下の場合、または x が負で y が整数でない場合は、errno に EDOM が設定され、0.0 が返されます。

double log( double x );

ネイピア数 e を底とする対数 (logex) を取得します。x が正でない場合は、errno に EDOM が設定され、- HUGE_VAL が返されます。

double log10( double x );

10 を底とする対数 (log10x) を取得します。x が正でない場合は、errno に EDOM が設定され、- HUGE_VAL が返されます。

double sin( double th );
double cos( double th );
double tan( double th );

三角関数です。それぞれ、サイン (正弦)、コサイン (余弦)、タンジェント (正接) を取得します。th はラジアン単位で指定します。

double asin( double y );
double acos( double x );
double atan( double z );
double atan2( double y, double x );

逆三角関数です。それぞれ、アーク サイン (逆正弦)、アーク コサイン (逆余弦)、アーク タンジェント (逆正接) を取得します。atan2 y/x はアーク タンジェントを返します。ラジアン単位の角度 -π/2 ～ +π/2 (主値) が返されます。

asin に対して -1.0 ～ +1.0 に収まらない数を指定すると、errno に EDOM が設定され、指定した値の符号に従って - 1.0 または 1.0 が返されます。

acos に対して -1.0 ～ +1.0 に収まらない数を指定すると、errno に EDOM が設定され、0.0 が返されます。

atan2 の x に 0 を指定すると、atan2 は 0 を返します。

double sinh( double y );
double cosh( double x );
double tanh( double z );

双曲線関数です。それぞれ、ハイパーボリック サイン (双曲線正弦)、ハイパーボリック コサイン (双曲線余弦)、ハイパーボリック タンジェント (双曲線正接) を取得します。結果の絶対値が大きすぎる場合は、errno に ERANGE が設定され、結果の符号に従って HUGE_VAL または - HUGE_VAL が返されます。

double floor( double y );
double ceil( double x );

floor は小数点以下を切り捨て、ceil は小数点以下を切り上げて、double 型で表現した整数値を返します。

double modf( double d, double* wp );

d の整数部分を *wp に格納して、d の小数部分を返します。

double frexp( double d, int* y );
double ldexp( double x, int y );

frexp は、d を x×2y に分解します。d が 0.0 以外の場合、x は 0.5 以上 1.0 未満になります。d が 0.0 の場合、x は 0.0 になります。

ldexp は、x×2y を返します。

int _getfcw( void );
void _setfcw( int mode );

浮動小数点演算コプロセッサ (FPU) の丸めモードを取得または設定します。_getfcw の戻り値と mode 引数は、次のいずれかです。

マクロ定義 | 値 | 意味
_RND_NEAR | 0 | 最近値へ (Light C の既定値)
_RND_MINUS | 1 | 負の無限大方向へ
_RND_PLUS | 2 | 正の無限大方向へ
_RND_ZERO | 3 | ゼロ方向へ


時間関数

時間関数 (time.h)

clock_t clock( void ); [OS]

プログラム起動の瞬間から経過した時間を取得します。clock() / CLOCKS_PER_SEC が秒数になります。Light C の場合、clock() はミリ秒単位の値を返します。

time_t time( time_t* ptr ); [OS]

現在の時刻を time_t 型で取得します。ptr に NULL 以外を使用すると、*ptr に戻り値と同じ値が設定されます。

Light C では、time_t は long として定義されており、グリニッジ標準時間 (ロンドン時間、GMT) 1970/1/1 00:00:00 からの経過秒数を表します。これは多くのコンパイラで採用されている方法です。この time_t では、1970/1/1 から 2038/1/18 までの日時を表すことができます。

struct tm* gmtime( time_t* ptr );
struct tm* localtime( time_t* ptr );

ptr で指定された time_t 値を tm 構造体に変換します。gmtime ではグリニッジ標準時間 (ロンドン時間)、localtime ではローカル時間 (Light C では日本時間) が tm 構造体に格納されます。指定する time_t 値は、通常 time() で取得します。

tm 構造体には、次のメンバがあります。これは ISO/JIS/ANSI の規定です。
struct tm {
int tm_sec; | // 秒 (0-59)
int tm_min; | // 分 (0-59)
int tm_hour; | // 時 (0-23)
int tm_mday; | // 日 (1-31)
int tm_mon; | // 月 - 1 (0-11)
int tm_year; | // 年 - 1900
int tm_wday; | // 曜日 (0-6)
int tm_yday; | // 年通算日 (0-365)
int tm_isdst; | // 季節時間フラグ (-1)
};

gmtime と localtime が返す値は、ライブラリ内部の単一の静的な tm 構造体へのポインタです。そのため、これらの関数 (または ctime) を再び呼び出すと、最初の戻り値の内容が変化します。返された tm 値を確実に保存するには、返されたポインタをそのまま保存するのではなく、次のように tm 構造体の内容をコピーしてください。
time_t t = time( NULL );
struct tm tim = *localtime( &t );

time とは異なり、gmtime と localtime は OS の API を呼び出さないため、OS には依存しません。Light C (および多くのコンパイラ) の gmtime と localtime は、1970/1/1 00:00:00 GMT からの経過秒数を表す time_t 値を、ISO/JIS/ANSI 規定の tm 構造体に変換します。

time_t mktime( struct tm* tim );

tm 構造体で示されたローカル時間 (日本時間) を time_t 値に変換します。localtime の逆の関数です。

char* ctime( time_t* ptr );
char* asctime( struct tm* tim );

日時を文字列に変換します。日時は、ctime では time_t へのポインタで、asctime では tm 構造体へのポインタで指定します。 次のような 25 文字 (末尾の 0 を入れて 26 バイト) の文字列が返されます。
Wed Aug 10 01:12:48 1999\n

ライブラリ内部の静的な領域へのポインタが返されるため、これらの関数を再び呼び出すと、最初の戻り値の内容が変化します。

size_t strftime( char* buf, size_t len, char* form, struct tm* tim );

日時 tim を書式 form に従って文字列化し、最大 len-1 バイトまで buf に格納します。文字列の末尾には 0 が付加されます。変換後の文字列の長さが len-1 以下の場合は文字列の長さが返され、長さが超えた場合は 0 が返されます。

form には、sprintf と同様の形式で書式を指定します。ただし、使用できる変換指定子が異なります。strftime では、次の変換指定子を使用できます。

指定子 | 出力例 | 説明
%a, %A | 水 | 曜日 (処理系依存)
%b, %B | 8 月 | 月 (処理系依存)
%c | 99-08-04 13:35:52 | 日付および時刻 (処理系依存)
%d | 07 | 2 桁の日付 (01 ～ 31)
%H | 07 | 2 桁の時間 (00 ～ 23)
%I | 07 | 2 桁の時間 (00 ～ 11)
%j | 077 | 3 桁の年通算日 (001 ～ 366)
%m | 07 | 2 桁の月 (01 ～ 12)
%M | 07 | 2 桁の分 (00 ～ 59)
%p | AM | 午前と午後の区別 (処理系依存)
%S | 07 | 2 桁の秒 (00 ～ 59)
%U | 07 | 日曜日を週の先頭とした年通算週 (00 ～ 53)
%w | 06 | 日曜日を 0 とした 1 桁の曜日 (0 ～ 6)
%W | 07 | 月曜日を週の先頭とした年通算週 (00 ～ 53)
%x | 99-08-04 | 日付 (処理系依存)
%X | 13:35:52 | 時刻 (処理系依存)
%y | 99 | 西暦下 2 桁
%Y | 1999 | 西暦年
%Z | TOKYO | 時間帯の名前 (処理系依存)
%% | % | % 自体

double difftime( time_t t1, time_t t2 );

時間の秒単位の差 (t1 - t2) を double 値で返します。


シグナル関数

シグナル関数 (signal.h)

void (*signal( int sig, void(*hdlr)(int) ))(int);

シグナルに対する応答を登録します。登録を定義する void func( int ) 型のハンドラ関数を第 2 引数に指定します。これまで登録されていたハンドラ関数へのポインタが返されます。signal

関数のプロトタイプは、次のように記述しても同じです。
typedef void (*_sighdlr_t)( int );
_sighdlr_t signal( int sig, _sighdlr_t hdlr );

sig には、次のいずれかの定数を使用して、シグナルの種類を指定します。

定数 | 意味
SIGABRT | 異常終了。abort から呼び出されます。
SIGFPE | 0 による除算
SIGILL | 不正な命令
SIGINT | 割り込み
SIGSEGV | 不正なメモリ アクセス
SIGTERM | 終了要求
_SIGNULLPTR | NULL ポインタへの代入。_nullptr_chk から呼び出されます。
_SIGSTKOVER | スタック オーバーフロー。_stack_chk から呼び出されます。

先頭に下線 (_) が付いている定数は、ISO/JIS/ANSI 規格外です。

初期状態では、すべてのシグナルに対して、それぞれ既定のハンドラ関数が定義されています。 既定のハンドラ関数の動作は、-os によって異なります。-os:dos が有効な場合は、ランタイム エラー を stderr に表示した後、_exit( EXIT_FAILURE ) でプログラムを終了します。-os:none が有効な場合は、何も行わずに呼び出し側に戻ります。

hdlr には、ハンドラ関数か、次のいずれかの定数を指定します。

定数 | 意味
SIG_DFL | 既定のハンドラに戻します。
SIG_IGN | このシグナルを無視することを指定します。

ハンドラ関数の引数には、発生したシグナルを示す SIGxxx 値が渡されます。このため、1 つのハンドラ関数で複数の種類のシグナルを区別して処理できます。

登録したハンドラ関数は、一度しか使用されません。つまり、あるシグナルが発生してハンドラ関数が呼び出されると、そのシグナルのハンドラは、SIG_DFL に戻ります。同じハンドラを引き続き使用するには、ハンドラ関数の中で signal を呼び出し、自らを再び登録する必要があります。

Light C では、ユーザーが明示的に該当する SIG??? 値を指定して raise 関数を呼び出さない限り、SIGABRT、_SIGNULLPTR、_SIGSTKOVER 以外のシグナルは起動されません。

int raise( int sig );

現在登録されているハンドラ関数を呼び出します。sig には、signal 関数の sig 引数と同じ定数を指定します。sig に対するハンドラは、この後既定に戻ります。
例 | void handler( int sig ) { printf( "abort!\n" ); }
 | main() {
 | signal( SIGABRT, handler );
 | abort(); // 登録ハンドラが消費される
 | abort(); // 再び既定のハンドラが使用される
 | }
結果 |
 | abort!
 | R.1100 abnormal termination


ロング ジャンプ

ロング ジャンプ (setjmp.h)

int setjmp( jmp_buf env );

longjmp のジャンプ先をあらかじめ記憶します。env に現在の状態が記憶され、0 が返されます。jmp_buf は、setjmp.h で構造体の配列として定義されていますが、その内容を気にする必要はありません。

void longjmp( jmp_buf env, int rv );

setjmp で記憶した場所にジャンプします。この関数を利用すると、たとえば、関数呼び出し階層の深いレベルから、一気に数段上のレベルに戻ることができます。

env には、setjmp で内容を記憶した変数を指定します。プログラムの実行は、その env を記憶した setjmp 関数から戻ったかのように続行されます。rv には、setjmp 関数からの (疑似的な) 戻り値を指定します。通常、rv には、最初の setjmp 呼び出しと区別できるように、0 以外の値を指定します。

setjmp 関数を呼び出した関数とは異なる関数から、その記憶場所への longjmp を呼び出すことができます。ただし、setjmp を呼び出した関数が終了した後で、longjmp 関数を呼び出すことはできません。

複数の env 変数を定義できるため、任意の数のジャンプ先を setjmp で記憶できます。
例 | jmp_buf env; | // ジャンプ先記憶域
 | void sub1() {
 | longjmp( env, 7 ); | // 戻り値 7 でジャンプ
 | printf( "never\n" ); | // この文は実行されない
 | }
 | void sub2() {
 | sub1();
 | }
 | main() {
 | int r = setjmp( env ); | // ここを記憶
 | if ( r == 0 ) { | // 登録時は戻り値 0
 | printf( "registered\n" );
 | sub2(); | // この下でジャンプが行われる
 | printf( "never\n" ); | // この文は実行されない
 | }
 | else | // ジャンプで戻ったときは戻り値 7
 | printf( "returned with %d\n", r );
 | }
結果 |
 | registered
 | returned with 7


プロセッサ/メモリ直接アクセス関数

プロセッサ/メモリ直接アクセス関数 (dos.h) [LC]

メモ dos.h およびその中の関数は、ISO/JIS/ANSI 規格ではありません。これらの関数の名前については、非 ISO/JIS/ANSI ヘッダーの dos.h をインクルードしない限り有効にならず、通常は他の名前と競合する可能性がないため、先頭に下線 (_) は付きません。

int peekw( unsigned seg, unsigned off );
char peekb( unsigned seg, unsigned off );
int peekwf( void far* ptr );
char peekbf( void far* ptr );

メモリのデータを読み出します。peekw と peekwf は 2 バイト、peekb と peekbf は 1 バイトのデータを読み出します。peekw と peekb はアドレス seg:off から、peekwf と peekbf はアドレス ptr からデータを読み出します。これらの関数は、マクロで定義されています。
例 | int d = peekw( 0xA800, 0x0000 ); | // A800:0000 から 2 バイトを取得
 | int far* ptr = (int far*)0xA8000000;
 | d = *ptr; | // このように書いても同じ

void pokew( unsigned seg, unsigned off, int data );
void pokeb( unsigned seg, unsigned off, char data );
void pokewf( void far* ptr, int data );
void pokebf( void far* ptr, char data );

上の peek 系関数とは逆に、メモリにデータを書き込みます。
例 | pokeb( 0xA800, 0x0000, 'A' ); | // A800:0000 に 41h を書き込む
 | int far* ptr = (int far*)0xA8000000;
 | *ptr = 'A'; | // このように書いても同じ

int inportw( int no );
char inportb( int no );

プロセッサの no 番の I/O ポートから 2 バイトまたは 1 バイトのデータを入力します。

これらの関数は、_macro を使って定義されています。

void outportw( int no, int data );
void outportb( int no, char data );

プロセッサの no 番の I/O ポートへ 2 バイトまたは 1 バイトの data を出力します。

これらの関数は、_macro を使って定義されています。
例 outportw( 0x70, 'A' ); // 70h 番ポートへ 41h を出力

unsigned FP_SEG( void far* ptr );
unsigned FP_OFF( void far* ptr );
void far* MK_FP( unsigned seg, unsigned off );

C 言語の far ポインタと、アセンブラ レベルのセグメントおよびオフセットとを相互に変換します。

FP_SEG は、ポインタ ptr のセグメント部分を取得します。FP_OFF は、ポインタ ptr のオフセット部分を取得します。MK_FP は、セグメント値とオフセット値から far ポインタを作成します。

これらの関数は、マクロで定義されています。

void get_regs( union REGS* regs );
void set_regs( union REGS* regs );

レジスタの現在の値を取得または設定します。

REGS は、dos.h で次のように定義されています。
struct WORDREGS {
unsigned ax;
unsigned bx;
unsigned cx;
unsigned dx;
unsigned si;
unsigned di;
unsigned cflag;
};
struct BYTEREGS {
unsigned char al, ah;
unsigned char bl, bh;
unsigned char cl, ch;
unsigned char dl, dh;
};
union REGS {
struct WORDREGS x;
struct BYTEREGS h;
};

get_regs は、現在のレジスタ値を regs に格納します。

set_regs は、regs の値をプロセッサのレジスタに格納します。

void get_sregs( struct SREGS* sregs );

セグメント レジスタの現在の値を取得します。

SREGS は、dos.h で次のように定義されています。
struct SREGS {
unsigned es;
unsigned cs;
unsigned ss;
unsigned ds;
};

int int86( int no, union REGS* iregs, union REGS* oregs );

iregs の値を sp、bp 以外の各レジスタに設定し、8086 プロセッサの no 番のソフトウェア割り込みを実行して、実行後のレジスタ値を oregs に格納します。割り込み終了時点の AX レジスタの値を返します。

「割り込みハンドラ」も参照してください。
例 | union REGS regs;
 | regs.h.dl = 'A';
 | regs.h.ah = 2;
 | int86( 0x21, &regs, &regs ); | // 'A' と表示

int int86x( int no, union REGS* iregs, union REGS* oregs, struct SREGS* sregs );

iregs および sregs の値を各レジスタに設定し、8086 プロセッサの no 番のソフトウェア割り込みを実行して、実行後のレジスタ値を oregs および sregs に格納します。cs、ss、sp、bp の値は無視されます。割り込み終了時点の AX レジスタの値を返します。

int intdos( int no, union REGS* iregs, union REGS* oregs ); [OS]

iregs の値を sp、bp 以外の各レジスタに設定し、no 番の MS-DOS ファンクション コール (int 21h) を実行して、実行後のレジスタ値を oregs に格納します。

割り込み終了時点の AX レジスタの値を返します。

MS-DOS ファンクション コールでエラーが発生した場合、つまりキャリーフラグがセットされた場合は、errno にエラー コードが設定されます。
例 | union REGS regs;
 | regs.h.dl = 'A';
 | intdos( 2, &regs, &regs ); | // 'A' と表示

int intdosx( int no, union REGS* iregs, union REGS* oregs, struct SREGS* sregs ); [OS]

intdos のバリエーションです。int86 に対する int86x に相当します。

inthdlr_t getvect( int no );
void setvect( int no, inthdlr_t func );

getvect は、no 番割り込みに設定されている割り込みハンドラのアドレスを取得します。setvect は、func を no 番割り込みのハンドラとして登録します。 inthdlr_t は、dos.h で次のように定義されています。

typedef void interrupt far (*inthdlr_t)( void );

これらの関数は、メモリ上の割り込みベクタに直接アクセスします。MS-DOS 互換環境では、代わりにファンクション コール 25h および 35h の使用が推奨されているため、MS-DOS 環境では intdos 関数を使用してください。


その他の OS 独立関数

int abs( int num ); (stdlib.h)
long labs( long num );

絶対値を返します。

参照 fabs

div_t div( int dividend, int divisor ); (stdlib.h)
ldiv_t ldiv( long dividend, long divisor );

dividend を divisor で割り、商と剰余を返します。結果は次の構造体で返されます。
typedef struct {
int quot; | // 商
int rem; | // 剰余
} div_t;
typedef struct |
long quot; | // 商
long rem; | // 剰余
} ldiv_t;

参照 fmod

void qsort( void* base, size_t num, size_t size, int (*cmp)(void*, void*) ); (stdlib.h)

クイック ソートのアルゴリズムで配列要素を並べ替えます。サイズ size の要素が num 個並んだ配列 base を、関数 cmp の判定に従って並べ替えます。

関数 cmp は、並べ替えの最中に繰り返し呼び出されます。2 つの引数には、配列 base の要素へのポインタが渡されます。関数 cmp からは、第 1 引数の要素が第 2 引数の要素より小さい場合には負の値を、等しい場合は 0 を、大きい場合は正の値を返す必要があります。要素の大小関係は、関数 cmp の実装で自由に決定できます。

次の例では、標準ライブラリ関数 strcmp を使用して、都市名の配列を並べ替えています。
char city[][12] = {
"Tokyo",
"Osaka",
"Nagoya",
"Fukuoka",
"Sapporo"
};
int size = sizeof( city[0] ); | // 都市名文字列のサイズ
int num = sizeof( city ) / size; | // 都市名の数
qsort( city, num, size, strcmp );
for ( int i = 0; i < num; i++ )
printf( "%s\n", city[i] );

結果は次のとおりです。
Fukuoka
Nagoya
Osaka
Sapporo
Tokyo

これに対して、たとえば、char *[n] 型の配列 (ポインタの配列) を strcmp で並べ替えることはできません。そのような配列を並べ替えるには、int func( char**, char** ) 型の比較関数を用意する必要があります。

void* bsearch( const void* key, const void* base, size_t num, size_t size, int (*cmp)(void*, void*) ); (stdlib.h)

二分検索のアルゴリズムで配列要素を検索します。配列は昇順にソートされている必要があります。サイズ size の要素が num 個並んだ配列 base から、値が key と一致する最初の要素を関数 cmp の判定に従って検索します。関数 cmp の形式は、qsort の cmp と同じです。一致する要素がない場合は、NULL が返されます。

たとえば、上の city 配列から "Osaka" へのポインタを取得するには、次のように記述します。
char* ptr = (char*)bsearch( "Osaka", city, num, size, strcmp );

int rand( void ); (stdlib.h)
void srand( unsigned seed );

rand は、0 ～ 32767 (RAND_MAX) までの疑似乱数を生成します。srand に任意の unsigned 値を渡すことにより、生成される乱数系列を変更できます。srand を呼び出さない限り、rand は、プログラムを起動するたびに毎回同じ乱数系列を生成します。

_max( a, b ); (stdlib.h)
_min( a, b );

それぞれ 2 つの引数のうち大きい方と小さい方の値を返します。

次のようにマクロ定義されています。
#define _max( a, b ) ((a) >= (b) ? (a) : (b))
#define _min( a, b ) ((a) <= (b) ? (a) : (b))

offsetof( s, m ); (stddef.h)

構造体メンバのオフセットを取得するマクロ関数です。次の例のように使用します。
struct s { long a; short b; };
int x = offsetof( struct s, a ); | // x = 0
int y = offsetof( struct s, b ); | // y = 4

char* strerror( int errnum ); (string.h)

コンパイラごとに定義されるエラー コードの意味を説明する文字列を返します。Light C では、errnum に errno と同じエラー コードを指定します。

assert( ex ); (assert.h)

assert は、実行時に式の値をチェックするためのマクロで、デバッグ目的で使用します。ex の値が実行時に評価され、偽 (0) であれば指定した方法で通知されます。マクロ NDEBUG を定義してコンパイルすると、assert マクロは消去され、コードは生成されません。

-os:dos が有効な場合は、ex が偽に評価されると、最初にソース ファイル名と行番号が stderr に出力され、次に raise(SIGABRT) が呼び出されて、ランタイム エラー R.1100 でプログラムが終了します。

-os:none が有効な場合は、ex が偽に評価されると、単に raise(SIGABRT) が呼び出されます。この場合は、あらかじめ signal() で指定しておかない限り、何も行われません。
例 | assert( ptr != NULL ); | // ポインタが NULL でないことを確認
 | assert( ptr ); | // 同上
 | assert( 0 ); | // このコードが実行されたら常に失敗
 | #define NDEBUG
 | assert( 0 ); | // この assert マクロは無効

void abort( void ); (stdlib.h)

raise( SIGABRT) を呼び出すことにより、プログラムをコード 2 (EXIT_FAILURE) で異常終了させます。この動作は、signal 関数で変更できます。

void va_start( va_list lst, arg ); (stdarg.h)
type va_arg( va_list lst, type );
void va_end( va_list lst );

可変個の引数を受け取る関数の引数にアクセスするときに使用します。

まず、va_list 型の変数を宣言します。va_list は、stdarg.h で char* と定義されています。その後、最後の固定引数とともに va_start を呼び出すことにより、可変引数の先頭を知らせます。次に、va_arg を繰り返し呼び出して、可変引数を順に取得します。type には各可変引数の型の名前 (int など) を指定します。最後に、va_end を呼び出して、処理の終了を知らせます (省略可能)。
void message( int num, ...) {
va_list lst;
va_start( lst, num );
for ( int i = 0; i < num; i++ ) {
char* a = va_arg( lst, char* );
printf( "[%s]", a );
}
va_end( lst );
}
main() {
message( 3, "A", "BC", "123" ); // "[A][BC][123]" と表示される
}

long _asmcode( void far* code, long data ); (stdlib.h)

機械語コードを直接実行します。code には、実行する機械語コードのアドレスを指定します。data は、機械語コードに DX:AX レジスタで渡されます。機械語コードで DX:AX に値を設定すると、その値が _asmcode の戻り値になります。機械語コードでは、最後に RETF (far リターン) 命令 CBh を実行する必要があります。
_asmcode( "\xE6\x03\xCB", 123 );
// 03 番ポートに 123 を出力して far リターン
// ("out 3, al" + "retf")

参照 インライン アセンブラ、レジスタの保存

Copyright © Tama Software Ltd, 1999-2010. ← → 目次 索引


入出力関数

入出力関数 (stdio.h) [OS]

管理

FILE* fopen( const char* fname, char* acc );

ファイル fname を開きます。成功すると、ファイルの読み書きに利用できる FILE 構造体が返されます。失敗すると、errno に理由コードが設定され、NULL が返されます。

アクセス モード acc には、次のいずれかの文字列を指定します。

文字列 | 説明
"r" | 既存ファイルをテキスト モードで読み出し専用に開く。
"w" | テキスト モードで書き込み専用に新規ファイルを作成する。既存の同名ファイルは削除される。
"a" | テキスト モードで書き込み専用に既存ファイルを開く。ファイルが存在しない場合は、新規作成する。ファイル ポインタはファイルの末尾に移動する (追加書き込み用)。
"rb", "wb", "ab" | バイナリ モードで開くことを除き、それぞれ "r"、"w"、"a" と同じ。
"r+" | 既存ファイルをテキスト モードで読み書き用に開く。
"w+" | 既存ファイルをテキスト モードで読み書き用に開く。ファイルが存在しない場合は、新規作成する。
"a+" | ファイル ポインタがファイルの末尾に移動することを除き、"w+" と同じ。
"r+b", "w+b", "a+b" | バイナリ モードで開くことを除き、それぞれ "r+"、"w+"、"a+" と同じ。

acc 文字列内の各文字の順番は自由です。たとえば、"r+b" の代わりに "rb+" と書いて同じです。

fopen で開いたファイルは、fclose で閉じます。

なお、4 つの標準入出力デバイスが最初から自動的に開かれます。

テキスト モードとバイナリ モード (cooked モードと raw モード)

テキスト モードとバイナリ モードの違いは、改行コード (\r\n) と Ctrl+Z コード (0x0A) の扱いに関係します。テキスト モードで開いた FILE を介して外部ファイルからデータを読み込んだ場合は、\r\n (0x0D,0x0A) という改行コードが単一の \n (0x0A) に変換されます。逆に、テキスト モードの FILE を介して \n を外部ファイルに書き込むと、実際には \r\n が書き込まれます。また、テキスト モードの FILE から Ctrl+Z が読み込まれると、ファイルの終端 (EOF) に達したものと見なされます。

FILE* freopen( const char* fname, char* acc, FILE* fp );

開いているファイル fp を閉じて、別のファイルをオープンし、fp に関連付けます。fp に NULL を指定すると、fopen と同じになります。fp が返されます。fp を閉じるときにエラーが発生しても、無視されます。

この関数は、stdout などの標準入出力を別のファイルにリダイレクトする場合によく使用されます。
例 | freopen( "output.log", "w", stdout );
 | printf( "Hello\n" ); | // output.log に書き込まれる

acc の詳細については、fopen の説明を参照してください。

int fclose( FILE* fp );

fopen で開いたファイル fp を閉じます。成功すると 0、失敗すると -1 が返されます。

int fflush( FILE* fp );

書き込み可能なファイルでは、ファイル バッファの内容が物理ファイルに書き込まれます。fflush を呼び出さなくても、ファイルを閉じればファイル バッファの内容が物理ファイルに書き込まれます。

読み出し可能なファイルでは、物理ファイルの内容がファイル バッファに読み出されます。

int fseek( FILE* fp, long offs, int org );
int fsetpos( FILE* fp, fpos_t* ptr );
int rewind( FILE* fp );

ファイルの位置を指定します。成功すると 0、失敗すると -1 が返されます。

fseek の org には、次のいずれかを指定します。

SEEK_SET | offs に絶対的な位置を指定
SEEK_CUR | offs に現在の位置からのオフセット (正または負) を指定
SEEK_END | offs に末尾からの距離 (0 以下) を指定

fsetpos は、fseek( fp, *ptr, SEEK_SET ) と同じです。

rewind は、ファイルを先頭に戻します。fseek( fp, 0, CUR_SET ) と同じです。

long ftell( FILE* fp );
int fgetpos( FILE* fp, fpos_t* ptr );

ファイルの位置を取得します。

ftell では、成功するとファイルの絶対位置、失敗すると -1L が返されます。

fgetpos では、成功するとファイルの絶対位置が *ptr に設定され、0 が返されます。失敗すると -1 が返されます。

int feof( FILE* fp );

過去にファイル fp の末尾を超えて読み出した場合は、0 以外が返されます。fseek、fsetpos、frewind、または clearerr を呼び出すと、この状態がクリアされ、再び 0 が返されるようになります。

int ferror( FILE* fp );

過去にファイル fp でエラーが発生した場合は、0 以外が返されます。clearerr を呼び出すと、この状態がクリアされ、再び 0 が返されるようになります。

void clearerr( FILE* fp );

ファイル fp の終端フラグとエラー フラグをクリアします。これにより、feof と ferror が再び 0 を返すようになります。

int setvbuf( FILE* fp, char* buf, int mode, size_t len );

ファイル fp のファイル バッファを設定します。または、出力ファイルをバッファリングしないことを指定します。この関数への呼び出しは、fopen または fopen でファイルを開いた後、そのファイルに対して他の操作を行う前に実行する必要があります。

mode には、次のいずれかを指定します。

_IONBF | 入出力をバッファリングしない
_IOFBF | 入出力を完全にバッファリングする
_IOLBF | 入出力を行ごとにバッファリングする

Light C では、行ごとのバッファリングはサポートされず、_IOLBF は _IOFBF と同じです。また、入力可能なファイルは、この関数による指定にかかわりなく常にバッファリングされます。

buf には、バッファとして使用するメモリまたは NULL を指定します。buf に指定したメモリは、ファイルを閉じるまで解放されてはなりません。NULL を指定すると、既定のバッファが使用されます。

len には、buf に指定したバッファの長さを指定します。少なくとも 20 (_FBUF_MARGIN * 2) 以上を指定する必要があります。buf に NULL を指定した場合、len は無視されます。

既定では、stdout、stderr、stdprn 以外のすべてのファイルがバッファリングされます。既定のファイル バッファのサイズは、256 バイトです。

void setbuf( FILE* fp, char* buf );

ファイル バッファを設定します。buf には、長さ BUFSIZ 以上のメモリか、NULL を指定します。buf に NULL 以外を指定した場合は、次の呼び出しと同じです。

setvbuf( fp, buf, _IOFBF, BUFSIZ );

buf に NULL を指定した場合は、次の呼び出しと同じです。

setvbuf( fp, NULL, _IONBF, 0 );

int remove( char* path );

ファイル path を削除します。成功すると 0 を返し、失敗すると errno に理由コードを設定して 0 以外を返します。path で指定したファイルが fopen などで開かれているとエラーになります。

int rename( char* oldpath, char* newpath );

ファイル oldpath の名前を newpath に変更します。成功すると 0 を返し、失敗すると errno に理由コードを設定して 0 以外を返します。同じドライブであれば、ファイルを別のディレクトリに移動することもできます。

char* tmpnam( char* buf );

重複しない一時ファイル名を取得します。TMP_MAX 回までの呼び出しが保証されています。buf には、L_tmpnam バイト以上のバッファか、NULL を指定します。NULL 以外を指定すると、作成されたファイル名が buf に格納され、buf が返されます。NULL を指定すると、作成されたファイル名は関数の内部バッファに格納され、そのアドレスが返されます。

FILE* tmpfile( void );

アクセス モード "w+b" で一時ファイルを開きます。一時ファイルは、閉じたときに自動的に削除されます。

int _filecpy( FILE* fpi, FILE* fpo, long len );

fpi の現在の位置以降の内容を fpo に最大 len バイト コピーします。len に負の値を指定すると、fpi の最後まですべての内容がコピーされます。成功すると 0、失敗すると 0 以外が返されます。

int _find_first( char* path, int attr, struct _find_t* dta );
int _find_next( struct _find_t* dta );

ワイルドカードに一致するファイル名を順に検索します。 最初に、_find_first を呼び出します。path には、検索するファイルのパスを指定します。「*.*」などのワイルドカードを指定したり、ディレクトリを含めることができます。attr には、次の値の組み合わせを指定します。

0x00 | 通常のファイルだけを検索する
0x02 | 隠しファイルも検索する
0x04 | システム ファイルも検索する
0x10 | ディレクトリも検索する

dta には、結果を受け取る _find_t 構造体のアドレスを指定します。_find_t 構造体は、stdio.h で次のように定義されています。
struct _find_t
{ char reserved[21]; | // 予約済み
char attrib; | // ファイルの属性
unsigned wr_time; | // 更新時刻 (DOS 形式)
unsigned wr_date; | // 更新日付 (DOS 形式)
long size; | // ファイルのサイズ
char name[13]; | // ファイル名
};

一致するファイルが存在する場合は、dta にそのファイルの情報が格納され、_find_first からは 0 が返されます。一致するファイルがない場合は、-1 が返されます。 続けて _find_next を呼び出すと、path に一致する他のファイルが順に検索されます。_find_first と同様に、一致するファイルがあれば 0、なければ -1 が返されます。

出力

テキスト モードのファイル構造体 FILE を介して出力した場合は、改行コード \n が \r\n に変換されます。stdout と stderr は、テキスト モードのファイル構造体として実装されています。

int printf( const char* form, ... );
int vprintf( const char* form, va_list lst );

データを書式化して標準出力 (stdout、通常はディスプレイ画面) に出力します。出力先が異なることを除き、sprintf および vsprintf と同じです。

int puts( const char* str );

ヌル終端文字列 str を標準出力 stdout に出力した後、改行を出力します。成功すると 0、失敗すると 0 以外を返します。文字列末尾の 0 は出力されません。

int putchar( int c );

1 バイト データ c を標準出力 stdout に出力し、成功すると c、失敗すると EOF を返します。

int fprintf( FILE* fp, const char* form, ... );
int vfprintf( FILE* fp, const char* form, va_list lst );

データを書式化してファイル fp に出力します。出力先が異なることを除き、 sprintf および vsprintf と同じです。

size_t fwrite( const void far* buf, size_t size, size_t num, FILE* fp );

buf からサイズ size のデータを num 個だけファイル fp に出力し、実際に出力された個数を返します。エラーが発生するか、EOF に到達した場合、戻り値は num より小さくなります。

Light C では、size × num の値が 64 KB を超えてはなりません。

Light C では、far データを簡単に出力できるように、buf が far ポインタとして実装されています。buf に near ポインタを渡すと、言語の仕様により、自動的に far ポインタに変換されます。

改行コード \n が \r\n に変換された場合は、戻り値 × size より長いデータが出力されています。

int fputs( const char far* str, FILE* fp );

ヌル終端文字列 str をファイル fp に出力し、成功すると 0、失敗すると 0 以外を返します。文字列末尾の 0 は出力されません。

int fputc( int c, FILE* fp );
int putc( int c, FILE* fp );

1 バイト データ c をファイル fp に出力し、成功すると c、失敗すると EOF を返します。この 2 つの関数は同じです。

int _putw( int c, FILE* fp );

2 バイトのデータを出力することを除き、fputc と同じです。下位 8 ビットが先頭バイトになります。

入力

テキスト モードのファイル構造体 FILE を介して入力した場合は、改行コード \r\n が \n に変換されます。また、Ctrl+Z コード 0x1A が EOF と見なされます。stdin は、テキスト モードのファイル構造体で実装されています。

int scanf( const char* form, ... );
int vscanf( const char* form, va_list lst );

標準入力 (stdin、通常はキーボード) からデータを入力します。データの入力元が異なることを除き、sscanf および vsscanf と同じです。

char* gets( char* buf );

標準入力 (stdin) から 1 行のデータを buf に読み込みます。成功すると buf、失敗すると NULL が返されます。buf の末尾に改行文字は付加されません。

int getchar( void );

標準入力 (stdin) から 1 バイトを入力して返します。ファイルが終了したか、エラーが発生した場合は、EOF が返されます。

int fscanf( FILE* fp, const char* form, ... );
int vfscanf( FILE* fp, const char* form, va_list lst );

ファイル fp からデータを入力します。データの入力元が異なることを除き、sscanf および vsscanf と同じです。

size_t fread( const void* buf, size_t size, size_t num, FILE* fp );

ファイル fp から最大 size × num バイトのデータを buf に読み込み、実際に読み込んだデータの個数を返します。実際に読み込まれたデータのバイト数は、戻り値 × size で求められます。エラーが発生するか、EOF に到達した場合、戻り値は num より小さくなります。

Light C では、size × num の値が 64 KB を超えてはなりません。

fp がテキスト モードの場合は、改行コード変換後のバイト数 ÷ size (端数切り捨て) が返されます。

char* fgets( char* buf, int len, FILE* fp );

ファイル fp から 1 行または len-1 バイトのデータを buf に読み込みます。成功すると buf、失敗すると NULL が返されます。 \n に遭遇するか、ファイルが終了するか、len-1 バイトを読み出した時点で入力が終了し、末尾に 0 が付加されます。\n で終了した場合は、\n 自体も buf に入ります。

int fgetc( FILE* fp );
int getc( FILE* fp );

ファイル fp から 1 バイトを入力して返します。ファイルが終了したか、エラーが発生した場合は、EOF を返します。この 2 つの関数は同じです。

int _getw( FILE* fp );

2 バイトのデータを入力することを除き、fputc と同じです。先頭バイトが下位 8 ビットになります。

int ungetc( int c, FILE* fp );

読み出した 1 バイトのデータ c を入力元に戻します。成功すると c、失敗すると EOF が返されます。次に同じ fp からデータを入力すると、この関数で戻したバイトが最初に読み出されます。

Light C では、連続して 10 (stdio.h の _FBUF_MARGIN) 回までバイトを戻すことができます。また、バイトを戻した後も、テキスト モードのファイルにおける改行コード変換によるずれを除き、ftell や fgetpos から正しい値が返されます。 ただし、ISO/JIS/ANSI 規格では、ungetc の呼び出しは連続 1 回しか保証されていません。また、ungetc 呼び出し直後の ftell や fgetpos の結果も保証されていません。

低水準入出力

次の関数は、バッファリングなどの処理を介在させることなく、直接 OS (MS-DOS) のファンクションを呼び出します。どの関数も、失敗すると -1 を返し、errno に理由コードを設定します。

fopen などの高水準関数は、内部でこれらの関数を呼び出します。

int _creat( const char* fname );

ファイルを新規作成し、そのハンドルを返します。同じ名前のファイルがあると、上書きされます。失敗すると -1 が返されます。

int _open( const char* fname, int acc );

既存のファイルを開き、そのハンドルを返します。既存のファイルがなければ失敗します。失敗すると -1 が返されます。

acc には、次のいずれかを指定します。

0 | 読み出し専用
1 | 書き込み専用
2 | 読み書き可能

int _close( int hdl );

ファイルを閉じます。hdl には、_open または _creat で取得したハンドルを指定します。成功すると 0、失敗すると -1 が返されます。

int _write( int hdl, const void far* buf, size_t size );

指定バイトのデータをファイルに書き込みます。成功すると実際に書き込まれたバイト数が返され、失敗すると -1 が返されます。

int _read( int hdl, void far* buf, size_t size );

ファイルから指定バイトのデータを読み出します。成功すると実際に読み出されたバイト数が返され、失敗すると -1 が返されます。

int _lseek( int hdl, long offs, int org );

ファイルの位置を設定します。新しいファイル位置が返されるため、ファイル位置の取得にも使用できます。org には、fseek と同じように SEEK_xxx 値を指定します。失敗すると -1 が返されます。

参照 入出力先の変更

Copyright © Tama Software Ltd, 1999-2010. ← → 目次 索引


メモリ割り当て関数

メモリ割り当て関数 [OS]

void* malloc( size_t size ); (stdlib.h)
void near* _nmalloc( size_t size );
void far* _fmalloc( size_t size );

メモリを取得します。失敗すると NULL を返し、errno に理由コードを設定します。

malloc は、small/medium モデルでは _nmalloc と、compact/large モデルでは _fmalloc と同じです。

_nmalloc は、near データとして使用できるメモリ、つまり DGROUP 先頭 (ds) から 64 KB 以内のメモリを割り当てます。_nmalloc で割り当てられるメモリの合計サイズは、64 KB から静的な near データとスタックのサイズを引いた値と同じです。

_fmalloc は、OS から直接メモリを取得します。

void free( void* mem ); (stdlib.h)
void _nfree( void near* mem );
void _ffree( void far* mem );

malloc、_nmalloc、または _malloc で取得したメモリを解放します。free は、small/medium モデルでは _nfree と、compact/large モデルでは _ffree と同じです。

_nfree は、実際には何も行いません。

_ffree は、メモリを OS に返します。

void* calloc( size_t num, size_t size ); (stdlib.h)

malloc( num * size ) と同じです。

void* realloc( void* mem, size_t size ); (stdlib.h)

メモリ mem のサイズを size に変更します。必要に応じて malloc が呼び出され、mem ブロックの内容がコピーされた後、その新しいメモリへのポインタが返されます。

size_t _msize( void _far* mem ); (stdlib.h)

malloc、_nmalloc、または _malloc で取得したメモリのサイズを調べます。

size_t _nmrest( void ); (stdlib.h)
long _fmrest( void );

今後 _nmalloc、または _malloc で取得できる残存メモリ サイズを取得します。


その他の OS 依存関数

その他の OS 依存関数 [OS]

void exit( int code ); (stdlib.h)
void _exit( int code );

プログラムを終了して、OS に戻ります。code には、0 ～ 255 の終了コードを指定します。exit では、開いているファイルがすべて閉じられ、一時ファイルが削除されます。_exit では、即座にプログラムが終了します。

void

atexit( void(*func)(void) ); (stdlib.h)

main 関数から戻ったとき、および exit 関数を呼び出したときに、プログラムの終了前に呼び出される関数を登録します。関数は 32 個まで登録できます。後で登録した関数から先に呼び出されます。
例 | void f1( void ) { printf( "exit process 1\n" ); }
 | void f2( void ) { printf( "exit process 2\n" ); }
 | main()
 | { atexit( f1 );
 | atexit( f2 );
 | }
結果 | exit process 2
 | exit process 1

char* getenv( const char* name ); (stdlib.h)

環境変数 name の値を取得します。その名前の環境変数が設定されていない場合は、NULL を返します。

int system( const char* cmd ); (stdlib.h)

OS のコマンドを実行します。

cmd に NULL 以外を指定すると、そのコマンドがコマンド プロセッサに渡され、実行されます。成功すると -1 以外が返されます。失敗すると -1 が返され、errno に理由コードが設定されます。

cmd に NULL を指定すると、OS のコマンド プロセッサを使用できるかどうかがチェックされ、可能なら 1、不可能なら 0 が返されます。Light C では、環境変数 COMSPEC が存在するかどうかで、このチェックの結果が決まります。
例 | system( "dir" );
 | system( "lc /?" );

int _system( const char* cmd, const char* param ); (stdlib.h)

コマンドを実行します。cmd には、起動する実行ファイルのパスを指定します。param には、cmd に渡すパラメータ文字列 (なければ NULL) を指定します。

この関数は、system() 関数とは異なり、コマンド プロセッサを使用しないで単純に実行ファイルを起動します。PATH 環境変数が使用されないため、現在のディレクトリにないファイルを起動するには、パスを明示的に指定する必要があります。また、コマンド プロセッサの内部コマンド ("dir" など) を実行することはできません。
例 | _system( "lc.exe", NULL );
 | _system( "c:\bin\lc.exe", "/?" );

char far* _getpsp( void ); (stdlib.h)

実行中のプログラムの "プログラム セグメント プレフィックス" (PSP) のアドレスを取得します。PSP とは MS-DOS が規定する情報ブロックで、MS-DOS で実行中のすべてのプログラムに 1 つずつ付加されています。

size_t _rest_stack( void ); (stdlib.h)

現在残っているおおよそのスタック サイズを取得します。_min_stack も参照してください。

size_t _min_stack( void ); (stdlib.h)

最小になった時点で残っていたおおよそのスタック サイズを取得します。

void perror( char* str ); (stdio.h)

現在の errno の意味を説明するメッセージを stderr に出力します。str に NULL 以外を指定すると、メッセージの先頭にその文字列が出力されます。


入力変換指定子

sscanf、vsscanf、scanf などの関数では、% を使用して、入力するデータの書式を指定します。たとえば、次のようになります。
char a[10];
int i, j; long li;
float f; double d;
sscanf( "ABC", "%s", a ); | // a[]="ABC"
sscanf( "ABC", "%2s", a ); | // a[]="AB"
sscanf( "ABC", "%c", a ); | // a[0]='A'
sscanf( "ABC", "%2c", &a ); | // a[0]='A', a[1]='B'
sscanf( "123", "%d", &i ); | // i=123
sscanf( "123", "%2d", &i ); | // i=12
sscanf( "1,2", "%d,%d", &i, &j ); | // i=1, j=2
sscanf( "123", "%ld", &li ); | // li=123
sscanf( "314e-2", "%f", &f ); | // f=3.14
sscanf( "314e-2", "%lf", &d ); | // d=3.14
sscanf( "AAABBC", "[AB]", a ); | // a="AAABB" (簡易正規表現)

入力変換指定子の構文は、次のとおりです。

%[*][width][modifier]type

入力変換指定子の構文は、多くの点で出力変換指定子を同じです。 modifier と type により、sscanf 関数などの引数に指定する変数の型が決まります。次はその例です。

指定 | 型
d,i,u,x | int* または unsigned*
ld,li,lu,lx | long* または unsigned long*
f,e,g | float*
lf,le,lg | double*
c,s | char*
C,S | wchar_t*
n | int*
p | void**
Fp | void far**
Np | void near**
Fd | int far*
Nd | int near*

* (アスタリスク)

% の直後に * を指定すると、そのデータは、変数に格納されずに読み飛ばされます。この場合、対応するアドレスを scanf などの引数に渡す必要はありません。
例 | int i;
 | sscanf( "1,2,3", "%*d,%*d,%d", &i ); | // i=3

width (出力幅)

入力データの最大バイト数を 10 進文字列で指定します。type が p の場合は無視されます。
例 | int a, b, c;
 | sscanf( "12345", "%1d%2d%3d", &a, &b, &c ); | // a=1, b=23, c=45

modifier (修飾子)

指定 | 説明
h | type で整数を指定する場合に、引数が int ではなく short へのポインタであることを示します。Light C では int と short が同一なので、効果はありません。
l | type が整数の場合は引数が int ではなく long へのポインタであることを示し、type が小数の場合は引数が float ではなく double へのポインタであることを示します。
L | type で小数を指定する場合に、引数が long double 型であることを示します。Light C では long double と double が同一なので、効果はありません。
F | 引数が far ポインタであることを示します。ただし、type が p の場合は、引数でポイントされるポインタが far であることを示します。
N | 引数が near ポインタであることを示します。ただし、type が p の場合は、引数でポイントされるポインタが near であることを示します。

type (型)

文字列をどのような種類の値として解釈するかを指定します。

指定 | 解析される文字列の構文 | 説明
d, i | [+|-]ddd | 文字列を符号付き 10 進数として解析し、結果を (long) int に格納します。
u | [+]ddd | 文字列を符号なし 10 進数として解析し、結果を (unsigned long) int に格納します。
X, x | [+][0x|0X]hhh | 文字列を 16 進数として解析し、結果を (unsigned long) int に格納します。文字列の先頭に 0x または 0X が付いていてもかまいません。
o | [+]ddd | 文字列を 8 進数として解析し、結果を (unsigned long) int に格納します。
q | [+]ddd | 文字列を 4 進数として解析し、結果を (unsigned long) int に格納します。[LC]
b | [+]ddd | 文字列を 2 進数として解析し、結果を (unsigned long) int に格納します。[LC]
p | hhh または hhh:hhh | ポインタ値の表現を読み込みます。small/medium モデルの場合と、modifier に N を指定した場合は、4 桁以下の 16 進数を入力し、near ポインタとして格納します。そうでない場合は、4 桁以下の 16 進数、コロン (:)、および 4 桁以下の 16 進数を順に入力し、far ポインタとして格納します。
s | [^ \t\n\v\f\r]... | ホワイトスペース以外のバイトを連続して入力し、末尾に 0 を付加して、結果を char [ ] に格納します。
c | (任意の n バイト) | 1 バイトを入力し、結果を char に格納します。width を指定した場合は、そのバイト数分のデータを連続して入力し、結果を char [ ] に格納します。
S | [^ \t\n\v\f\r]... | s と似ていますが、結果を wchar_t [ ] に格納する点が異なります。
C |  | c と似ていますが、結果を wchar_t または wchar_t [ ] に格納する点が異なります。
f,e,g,E,G | [+|-][ddd][.ddd][{E|e}ddd] | 文字列を小数として解析し、結果を float または double に格納します。
n |  | これまでに入力したバイト数を int に格納します。

c と C 以外では、入力データ先頭のホワイトスペースは読み飛ばされます。

参照 出力変換指定子

Copyright © Tama Software Ltd, 1999-2010. ← → 目次 索引


出力変換指定子

sprintf、vsprintf、printf などの関数では、% を使用して、出力するデータの書式を指定します。たとえば、次のようになります。
printf( "%s", "123" ); | // → "123"
printf( "%4d", 456 ); | // → " 456"
printf( "%05X", 254 ); | // → "000FE"
printf( "%-5s", "abc" ); | // → "abc "
printf( "%f", 12.56637061 ); | // → "12.566371"
printf( "%.2f", 12.56637061 ); | // → "12.56"
printf( "%e", 12.56637061 ); | // → "1.256637e+001"
printf( "%g", 12.56637061 ); | // → "12.5664"
printf( "xyz%n", &i ); | // i に出力バイト数 (3) が入る

出力変換指定子の構文は、次のとおりです。

%[flags][width][.precision][modifier]type

flags (フラグ)

- 出力内容より width が大きい場合に、左に寄せて出力します。出力内容より width が小さい場合は、効果がありません。
+ 負でない数に「+」を付加します。type が数値でなければ無視されます。
(空白) 同上
# 型がわかる形式で数値を出力します。
  • 8 進数 － 先頭に 0 が付加されます。
  • 16 進数 － 先頭に 0x または 0X が付加されます。
  • 浮動小数点数 － 必ず小数点が出力されます。g または G 形式の場合は、末尾の不要な 0 も削除されません。
, 整数を 3 桁ごとにカンマ (,) で区切ります。[LC]

width (出力幅)

(数字) 出力全体の桁数を指定します。先頭に 0 を付けると、余分な桁は文字 0 で埋められます。それ以外の場合は、スペース文字で埋められます。
* 次の int 型の引数で渡された値が使用されます。値が負の場合は、左寄せになります。
例 printf( "i=%*d\n", 10, i ); // i を 10 桁で表示

precision (精度)

(数字) 出力桁数を指定します。負の precision は無視されます。ピリオドだけを記述して数値を省略すると、0 と見なされます。効果は type によって異なります。
  • 整数 － 出力内容が指定桁数に満たない場合は、左側に文字 0 が補充されます。出力内容が指定桁数を超える場合は、効果がありません。precision が 0 で出力も 0 の場合は、何も出力されません。既定値は 1 です。
    例 printf( "%5.3d", 12 ); // " 012" と表示される
  • f, e, E － 小数点以下の桁数を指定します。0 を指定すると、flags に # を指定しない限り、小数点も出力されません。既定値は 6 です。
  • g, G － 整数部と小数部を合わせた桁数を指定します。既定値は 6 です。
  • 文字列 － 出力の最大桁数を指定します。
* width と同様に、次の int 型の引数で渡された値を使用します。

modifier (修飾子)

h | type で整数を指定する場合に、引数が short 型であることを示します。Light C では int と short が同一なので、効果はありません。
l | type で整数を指定する場合に、引数が long 型であることを示します。
L | type で小数を指定する場合に、引数が long double 型であることを示します。Light C では long double と double が同一なので、効果はありません。
F | type で文字列 (s) またはポインタ (p) を指定する場合に、引数が far ポインタであることを示します。
N | type で文字列 (s) またはポインタ (p) を指定する場合に、引数が near ポインタであることを示します。

type (型)

引数の型を指定します。

d | int 値を符号付き 10 進数として出力します。
i | d と同じです。
u | int 値を符号なし 10 進数として出力します。
X | int 値を符号なし 16 進数として出力します。10 ～ 15 の桁は 'A' ～'F' で表されます。
x | int 値を符号なし 16 進数として出力します。10 ～ 15 の桁は 'a' ～'f' で表されます。
o | int 値を符号なし 8 進数として出力します。
q | int 値を符号なし 4 進数として出力します。[LC]
b | int 値を符号なし 2 進数として出力します。[LC]
p | ポインタの値を 16 進数で出力します。
s | ヌル終端文字列へのポインタを受け取り、文字列を出力します。
c | int 値を文字として出力します。Shift-JIS の全角文字も出力できます。
S | ワイド文字列を出力します。
C | c と同じです。
f | double 値を通常の小数表現で出力します (例：12.566371)。
e | double 値を指数表現で出力します (例：1.256637e+001)。
E | e の代わりに E を出力することを除き、e と同じです (例：1.256637E+001)。
g | 数値の大きさに応じて、f または e のいずれかの書式で出力します (例：12.5664、2.99792e+008)。数値の絶対値が大きすぎて precision の桁数に収まらない場合と、数値の絶対値が 0.0001 より小さい場合は、e 形式が使用されます。それ以外の場合は、f 形式が使用されます。
G | e の代わりに E を出力することを除き、g と同じです。
n 次の引数で指される int 変数に、これまでに出力したバイト数を格納します。
例 printf( "xyz%n", &i ); // i に 3 が入る

メモ 1 % 自体を出力するには、「%%」と記述します。

メモ 2 char 型の数値は、関数に渡されるときに自動的に int 型に変換されるため (汎整数拡張)、int 型と同じように「%d」、「%X」などを使って表示できます。

メモ 3 float 型の数値は、関数に渡されるときに自動的に double 型に変換されるため、double 型と同じように「%f」、「%e」などを使って表示できます。

参照 入力変換指定子

Copyright © Tama Software Ltd, 1999-2010. ← → 目次 索引


ライブラリの再コンパイル

libsrc ディレクトリには、ライブラリのすべてのソース ファイルが収められています。これらのソース ファイルは C 言語またはアセンブラで記述されており、それぞれ Light C と Light Macro Assembler でコンパイルまたはアセンブルできます。

アセンブラのソース ファイルをアセンブルするには、Light Macro Assembler が必要です。このアセンブラは別売りですが、ライブラリのほとんどのソース ファイルは、行数が少ないので無料の体験版でもアセンブルできます。Microsoft MASM でもアセンブルできますが、その場合はバッチファイルやソース ファイルを多少変更する必要があります。

ライブラリを再コンパイルするには

  1. コマンド プロンプトを開き、Light C の各ツール (lc.exe、llib.exe など) と Light Macro Assembler (lasm32.exe) を使用できる状態にします。
  2. libsrc ディレクトリに移動します。
  3. mk.bat を実行します。すべてのライブラリ ファイルがコンパイルまたはアセンブルされ、ライブラリ (.llb) ファイルが生成されます。

手作業で個別にコンパイル/アセンブルする場合

メモリ モデル、実行環境、浮動小数点演算エミュレータを使用するかどうかなどに応じて、次のオプションを指定します。

libsrc\mk.bat と libsrc\lclib.mak を参考にしてください。

lc のオプション

lc.exe には、次のオプションを指定します。

lc -c -zl -o -gf <file>...

-c と -zl は必須です。さらに、必要に応じて次のオプションを追加します。

-am, -ac, -al | small 以外のメモリ モデルの場合
-os:none | 実行環境として MS-DOS を使用しない場合
-emul | 浮動小数点演算エミュレータを使用する場合

lasm のオプション

lasm -u -or -pl <file>

これらのオプションは、いずれも必須です。さらに、必要に応じて次のオプションを追加します。

-DFAR_C | medium または large モデルの場合
-DFAR_D | compact または large モデルの場合
-DFP_EMUL | 浮動小数点演算エミュレータを使用する場合


リンカ (LIL)

リンカ (Light Linker) LIL.EXE および LIL32.EXE は、Light Macro Assembler または Light C で作成した MS-DOS 標準形式のオブジェクト (OBJ) ファイルをリンクします。

Light Macro Assembler または Light C で作成したオブジェクト ファイルは、上記形式のオブジェクト ファイルに対応している他社のリンカ (Microsoft 社の LINK.EXE など) でも多くの場合はリンクできます。反対に、他社のコンパイラやアセンブラで作成した OBJ ファイルは、非標準の機能が使用されているために LIL ではリンクできない場合があります。

メモ LIL32.EXE は Windows のコマンド プロンプト内（32 ビット環境）で実行できます。LIL.EXE は MS-DOS (16 ビット環境) でも実行できますが、一部の新機能が使用できません。16 ビット版の LIL.EXE は、Light Macro Assembler for x86 にのみ付属します。このマニュアルでは単に LIL.EXE と記している場合がありますが、これらの説明は LIL32.EXE にも当てはまります。

デバッガ LID を使用する場合は、LIL.EXE を使用する必要があります。同様に、Microsoft 社のデバッガ SYMDEB を使用する場合は、同社の LINK.EXE を使用する必要があります。


リンカ LIL のコマンドライン構文

LIL は次の形式で実行します。

lil <obj-path>... [<link-option>...] [@<rsp-file>...]

オブジェクト ファイル名の拡張子を省略すると、自動的に「.OBJ」が追加されます。拡張子のないファイル名を指定するには、ファイル名の後にピリオド (.) だけを付加します。 <obj-path>、<link-option>、<rsp-file> を指定する順番は自由です。

例
> LIL HELLO
HELLO.OBJ をリンクします。
> LIL HELOLO1 HELLO2
HELLO1.OBJ と HELLO2.OBJ をリンクします。
> LIL HELLOC /C
HELLOC.OBJ をオプション/C でリンクします。

応答ファイル

コマンドラインに指定するリンカ オプションやオブジェクト ファイル名をファイルに記述しておくこともできます。この「応答ファイル」には、リンカ オプションやオブジェクト ファイル名をコマンドラインから入力する場合と同じ形式で並べます。各項目はスペース、タブ、または改行で区切ります。

コマンドラインでは、応答ファイル名の前にアッロマーク (＠) を付けて指定します。同時に通常のコマンドラインでオブジェクト ファイル名やリンカ オプションを追加することもできます。また、応答ファイル内からさらに別の応答ファイルを呼び出すこともできます。

例
> LIL @ABC.RSP /M
応答ファイル ABC.RSP の内容に /M を追加してリンクします。

参照

リンカ オプション

Copyright © Tama Software Ltd, 1999-2010. ← → 目次 索引


リンカ オプション

リンカ オプションにより、リンク方法をさまざまに制御できます。各リンカ オプションは、先頭にマイナス記号 (-) またはスラッシュ (/) を付けて指定します。大文字と小文字は区別されません。リンカ オプションを指定する順番は自由で、オブジェクト ファイル名の前後どちらにでも指定できます。

以下では、各リンカ オプションをアルファベット順に説明します。

/32

64 KB を超えるセグメントをリンクします。現在、LIL が 64 KB 超のセグメントをサポートしているファイル形式は、/B で作成される BIN 形式だけです。

/AMIN<hhhh>

.EXE ファイルの MINALLOC フィールドの値を指定します。作成したプログラムに OS から割り当てられる最小メモリ サイズの 1/16 を 16 進数で指定します。たとえば、/AMIN300 と指定すると、300 × 16 = 4800 バイトのメモリが割り当てられます。

通常、MINALLOC フィールドには適切な値が自動的に設定されるため、このオプションを指定する必要はありません。

/AMAX<hhhh>

.EXE ファイルの MAXALLOC フィールドの値を指定します。作成したプログラムに OS から割り当てられる最大メモリ サイズを指定します。指定方法は /AMIN と同じです。

/B[<seg-address>]

単純なバイナリ イメージ ファイル (拡張子 .bin) を作成します。BIN ファイルは COM ファイルと似ていますが、COM とは異なり先頭の 100h バイトが除去されません。

イメージを 1 以上のアドレスに配置する場合は、seg-address を指定します。たとえば、LIL /BFE00 と指定すると、FE00:0000 以降に配置して実行するためのバイナリ イメージが生成されます。

例
LIL F1.OBJ F2.OBJ /B
LIL F1.OBJ F2.OBJ /B1200

/C

COM 形式の実行ファイルを作成します。拡張子 .com を持つ実行ファイルが作成されます。このオプションを指定してリンクするプログラムは、あらかじめ COM 形式向けに作られている必要があります。

このオプションを指定せずに EXE 形式の実行ファイルを作成し、それを MS-DOS に付属のユーティリティ EXE2BIN を使用して COM 形式に変換することもできます。

/D

セグメントを MS-DOS 標準セグメント順序に従って配置します。これは、アセンブラのソースファイルに DOSSEG ディレクティブを記述することと同じです。

/E<file-name>

作成する実行ファイルの名前を指定します。<file-name> の拡張子を省略すると、実行ファイルの既定拡張子（.exe、.com、.hex など）が追加されます。

このオプションを指定しなければ、最初に指定したオブジェクト ファイル名の拡張子を実行ファイルの既定拡張子に取り替えた名前で実行ファイルが作成されます。

/H

最小の EXE 形式ファイルを作成します。/C を指定した場合、このオプションは無効です。

/HEX

インテル HEX 形式ファイルを生成します。「インテル HEX 形式」も参照してください。

/M[<file-name>]

マップ ファイルを作成します。<file-name> を省略すると、最初に指定したオブジェクト ファイル名の拡張子を「.MAP」に取り替えた名前でマップ ファイルが作成されます。マップ ファイルには、作成された実行ファイル内のセグメントの位置、サイズ、グローバル名の位置などが示されます。

/K<name>

ライブラリ検索パスを示す環境変数名を指定します。

例
LIL SAMPLE.OBJ /KLIBRARY

/L<path>

ライブラリを指定します。環境変数 LCLIB と同じ機能です。

例
LIL SAMPLE.OBJ /LC:\LIB\*.OBJ

<path> には、オブジェクト ファイルまたはライブラリ (.llb) ファイルを指定します。ワイルドカードも使用できます。

このオプションを指定すると、リンク対象のオブジェクト ファイルに解決できない外部名が含まれていた場合に <path> で指定したファイルが検索され、その名前を公開しているオブジェクト ファイルまたはライブラリ モジュールが自動的にリンクされます。

/PF

オプション /L で自動的にリンクされたオブジェクト ファイルの名前を表示します。

/PFL

オプション /L で指定されたオブジェクト ファイルを自動的にリンクする原因となった未解決名を表示します。

/R

警告メッセージが発生した場合に、戻り値 1 で LIL を終了します。通常は、エラーが発生した場合は戻り値 2、それ以外は戻り値 0 で OS に戻ります。

/RE0

エラーが発生しても、戻り値 0 で LIL を終了します。

/RL

HEX ファイル生成時に、拡張セグメント アドレス (ESA) レコードよりも拡張リニア (ELA) アドレス レコードを優先して使用します。「インテル HEX 形式」も参照してください。

/S<seg-name>=<seg-addr>［:<place>］

セグメント先頭のアドレスを絶対的に指定します。HEX ファイルを作成する場合にのみ有効です。

<seg-name> には、セグメント名を指定します。

<seg-addr> には、そのセグメントのアドレスを 4 桁の 16 進数で指定します。4 バイトの絶対アドレスではなく 2 バイトのセグメントのアドレスを指定します。その 16 倍が実効アドレスになります。この指定はアセンブラの SEGMENT 文の AT 属性に相当します。

<place> には、そのセグメント先頭のデータを配置するアドレスを 4 バイトの絶対アドレス (8 桁の 16 進数) で指定します。この指定はアセンブラの SEGMENT 文の PLACE_AT 属性に相当します。

  • <place> に NO を指定すると、そのセグメントは HEX ファイルに出力されません。これはアセンブラの SEGMENT 文に PLACE_AT NO と指定するのと同じです。
  • <place> に CNT を指定すると、直前のセグメントが配置された領域の直後のパラグラフ アドレス (16 で割り切れるアドレス) に配置されます。
  • <place> を省略すると、そのセグメントは <seg-addr> に配置されます。
  • /SSEG=:42A00 のように、<seg-addr> を省略して <place> だけを指定することもできます。

<place> は、セグメントの実行時アドレスと配置アドレスを異なる値に指定するためのオプションです。その場合は、<addr> に実行時のアドレスを指定し、<place> に静的な配置アドレスを指定します。このようなセグメントは、<place> に配置するように HEX ファイルに書き込まれますが、そのセグメント内のラベルへの参照は、そのセグメントが <place> ではなく <addr> にあるかのように生成されます。このようなセグメントを実行するには、その前にセグメントの内容を <place> から <addr> に移動しておく必要があります。

配置アドレスの決定にもセグメントのアライン属性が影響しますが、PARA が下限です。したがって、<place> を使って配置するセグメントには、PARA 以上のアライン属性を指定してください。Light C の場合は -csp オプションも参照してください。

なお、同じセグメントに AT または PLACE_AT 属性と /S オプションの両方を指定すると、/S オプションの値が優先されます。

「インテル HEX 形式」も参照してください。

例
LIL SAMPLE.OBJ /SCSEG=1A00
LIL SAMPLE.OBJ /SCSEG=1A00:F0000
LIL SAMPLE.OBJ /SS1=1A00:F0000 /SS2=:CNT

さらに例を示します。

LIL /HEX /SCODE=20C0 SAMPLE.OBJ

このコマンドは、セグメント CODE のセグメント アドレスを 20C0h に指定しています。これは、アセンブラのソースコードに次のように記述することと同等です。

CODE SEGMENT AT 20C0h

この結果、セグメント CODE はセグメント アドレスの 20C0h、つまり実アドレスの 20C00h に置かれることになります。

/TSD<additional-size>

スタックの追加サイズを 10 進数で指定します。STACK コンバイン属性を持つセグメントの合計サイズに、この値が加算されて、SP レジスタの初期値が決定されます。

/U

大文字と小文字を区別します。

オブジェクト ファイル中の名前 (セグメント名やグローバル名など) を照合する際、通常 LIL は大文字と小文字の区別を行いませんが、このオプションが指定された場合は区別を行います。

/UE

未解決の外部参照があった場合でも、実行ファイルを作成します。

/Y

16 ビット版の LIL.EXE で、使用するメモリを約 50KB 節約します。メモリ不足エラーが発生する場合に指定します。それでもメモリ不足が解消しない場合は、32 ビット版の LIL32.EXE を使用してください。


ライブラリ マネージャ (LLIB)

Light Macro Assembler や Light C には、ライブラリ マネージャ LLIB.EXE が付属しています。このツールは、オブジェクト (.obj) ファイル群からライブラリ (.llb) ファイルを作成します。.llb ファイルはリンカ LIL の入力ファイルとしてのみ使用でき、他社のリンカでは使用できません。

ライブラリの新規作成、ファイルの追加、または更新

llib a <lib-path> <obj-path>...

<obj-path> で指定した 1 つ以上のオブジェクト ファイルをライブラリ ファイル <lib-path> に格納します。

ライブラリ ファイル <lib-path> が存在しない場合は、新しく作成されます。ライブラリ内に <obj-path> と同じ名前のモジュール (同じファイル名のオブジェクト ファイル) が含まれている場合は、古いモジュールが新しいオブジェクト ファイルに置き換わります。

たとえば、次のように指定すると、a.obj と b.obj が small.llb に格納されます。

llib a small.llb a.obj b.obj

次のようにディレクトリを指定したり、ワイルドカードを使用することもできます。

llib a small.llb sub\a.obj d:\b.obj
llib a small.llb d:\obj\*.*

ライブラリ ファイル内の各モジュールは、オブジェクト ファイルの名前で区別されます。オブジェクト ファイルのディレクトリは、ライブラリ ファイルには記録されません。

モジュールの削除

llib d <lib-path> <module-name>...

<module-name> で指定した 1 つ以上のモジュールをライブラリ ファイル <lib-path> から削除します。<module-name> には、ディレクトリを除いたオブジェクト ファイル名を指定します。ワイルドカードは使用できません。

モジュールの抽出

llib e <lib-path> <module-name>...

<module-name> で指定した 1 つ以上のモジュールをライブラリ ファイル <lib-path> から抽出します。ワイルドカードは使用できません。抽出されたモジュールは、オブジェクト ファイルとして現在のディレクトリに置かれます。

モジュールの表示

llib l <lib-path>

ライブラリ ファイル <lib-path> に含まれているモジュール (オブジェクト ファイル) を一覧表示します。


EXE、COM、BIN、OBJ ファイルの形式

Light C と Light Macro Assembler は、MS-DOS 標準形式のオブジェクト (OBJ) ファイルを生成します。LIL はこの OBJ ファイルを受け取り、EXE、COM、BIN、HEX の各形式で実行イメージを出力します。

OBJ

MS-DOS で標準的に使用されていたオブジェクト ファイルの形式で、Relocatable Object Module Format (OMF) とも呼ばれます。通常、拡張子は .obj になります。現在も多くのツールがこの形式に対応しています。

この形式の OBJ ファイルは、多くのリンカに入力できます。たとえば、次のリンカがこの形式のオブジェクト ファイルに対応しています。

  • LIL (Light Macro Assembler や Light C に付属)
  • Microsoft 社の LINK.EXE
  • Borland 社の TLINK.EXE

また、この OBJ 形式の詳細については、多くの文書が公開されています。以下はその例です (2000/02/10 現在)。

  • Microsoft MSDN
  • アスキー刊『The MS-DOS Encyclopedia』 : ISBN4-87148-347-9, \8,030
  • http://developer.intel.com/design/intarch/PAPERS/ESC_FILE.HTM (英文)
  • http://www.wotsit.org/ (英文)

EXE [x86]

MS-DOS 標準の EXE 形式です。このファイルは、MS-DOS、Microsoft Windows の DOS 互換ウィンドウ、およびそれらと互換性のあるシステムで実行できます。

COM [x86]

MS-DOS 標準の COM 形式です。ファイルの先頭からコードおよびデータの 16 進コードが並ぶ単純な形式で、MS-DOS、Microsoft Windows、およびそれらと互換性のあるシステムで実行できます。BIN 形式と似ていますが、COM 形式ではファイル先頭がオフセット 100h に相当します。

BIN

ファイルの先頭からコードおよびデータの 16 進コードが並ぶ単純な形式です。

HEX

「インテル HEX 形式」を参照してください。

PE, NE

現在の Light Macro Assembler、Light C、LIL は、PE (Portable Excutable) および NE 形式をサポートしていません。この形式の実行ファイルを作成するには、Microsoft LINK.EXE、Borland TLINK.EXE などを使用する必要があります。


インテル HEX 形式

ここでは、インテル HEX 形式ファイルについて説明します。HEX ファイルは、プログラムイメージ（コードとデータを表すの 16 進数列）をテキストで表現したもので、主に ROM (Read Only Memory) 化プログラムを作成する場合に使用されます。HEX は米国インテル社が規定したファイル形式で、世界中で使用されています。

HEX ファイル

lil が生成する HEX ファイルは、このインテル HEX 形式に準拠しています。そのため、市販の多くのローダ、デバッガ、エミュレータ環境などで読み込むことができます。

HEX ファイルは、次のレコードを復帰/改行コード (0Dh, 0Ah) で区切って並べたものです。

  • タイプ 2 － アドレス レコード (ESA)
  • タイプ 4 － アドレス レコード (ELA)
  • タイプ 0 － データ レコード
  • タイプ 3 － 開始アドレス レコード
  • タイプ 1 － ファイル終了レコード

各レコードは、次の共通形式を持ちます。各行はコロン (:) で始まり、いくつかの 16 進数が続きます。

:llaaaattdddd...ddddss\r\n

  • 行頭にはコロン (:) が挿入されます。
  • 次の 2 桁の 16 進数 (ll) は、データ (dddd...dddd の部分) の長さを表します。
  • 次の 4 桁の 16 進数 (aaaa) は、データ レコードのアドレスです。
  • 次の 2 桁の 16 進数 (tt) は、レコードのタイプを表します。
  • 次の部分 (dddd...dddd) は、可変長の 16 進数データです。その長さは ll で示されています。
  • 最後の 2 桁の 16 進数 (ss) は、チェックサムです。レコード内のすべての 16 進数値を合計したとき、下位 2 桁が 00h になるように定められます。
  • 各行は 0Dh, 0Ah (\r\n) で区切られます。

各レコードの意味

lil が生成する HEX ファイルの先頭には、データが 0 以外のアドレスから始まる場合、アドレス レコードが出力されます。アドレス レコードには ESA と ELA の 2 種類があります。これらのレコードの詳細については、後方の「アドレス レコード」を参照してください｡
:02 0000 02 aaaa ss | ← ESA レコード
:02 0000 04 aaaa ss | ← ELA レコード

※実際のファイルに空白は挿入されません。

※aaaa は 10h 単位(ESA)または10000h 単位(ELA)のアドレスです。

※ss はチェックサムです。

次に、いくつかのデータ レコードが続きます。データ レコードが実際のプログラムコードとデータの内容を表します。
:nn aaaa 00 data... ss ← データ レコード

※nn はデータのバイト数です (最大 10h)。

※data... には実際のデータが nn 個続きます。

ソースコードの END 文で開始アドレスを指定した場合は、最後にタイプ 3 の開始アドレス レコードが作成されます。
:04 0000 03 seg-offs ss ← 開始アドレス レコード

※seg-offs は 4 バイトのセグメント:オフセット アドレスです。

最後に、必ずタイプ 1 のファイル終了レコードが出力されます。
:00 0000 01 ss ← 終了レコード

コードの書き方

アセンブラおよび C 言語のソースコードの書き方は、通常の実行ファイル (EXE, COM) を作成する場合と同じです。

ROM 化するプログラムでは、セグメントの絶対アドレスを指定する場合が多くなります。それには、ソースコード中で SEGMENT 文に AT 属性を指定する (アセンブラの場合) か、またはリンク時に lil の /S オプションを使用します。

アセンブル、コンパイル、リンク方法

Light Macro Assembler の場合 アセンブル方法は通常と同じですが、リンク時に lil に対して /HEX オプションを指定する必要があります。その結果、EXE や COM の代わりに HEX ファイルが生成されます。/E オプションで HEX ファイル名を指定することもできます。デフォルトでは、コマンドラインで一番最初に指定されたオブジェクト ファイルのベース名に拡張子「.HEX」を付けた名前になります。

Light C の場合 コンパイル オプション /HEX を指定します。または、コンパイルとリンクを個別に実行して、リンク時に /HEX オプションを指定します。

アドレス レコード

lil が生成する HEX ファイルでは、10000h 以上の配置アドレスを示すために、拡張セグメント アドレス (ESA) レコードと拡張リニア アドレス (ELA) レコードの一方または両方が出力される場合があります。

実際のデータの配置アドレスは、ESA レコード、ELA レコード、およびデータ レコードで決まります。この 3 種類のレコードには、いずれも 16 ビットの配置アドレス指定フィールドがあります。各レコードに記入された配置アドレスは、ESA レコードでは 10h バイト単位、ELA レコードでは 10000h バイト単位、データ レコードでは 1 バイト単位で解釈されます。

各データ レコードのデータが実際に配置されるアドレスは、そのデータ レコード自身が指定する 16 ビットアドレスと、直前の ESA および ELA レコードの指定アドレスを加算した値になります。たとえば、直前の ESA レコードが 0002h、ELA レコードが 0003h を指定している場合、データ レコードの配置アドレスには、2h * 10h + 3h * 10000h = 30020h が加算されます。

    -----------------------
    桁      7 6 5 4 3 2 1 0
    -----------------------
    ELA     L L L L          ← 直前の ELA アドレス レコードで指定されたアドレス
    ESA           S S S S    ← 直前の ESA アドレス レコードで指定されたアドレス
    DATA            D D D D  ← データ レコード内で指定されたアドレス
    -----------------------
    ADDR    A A A A A A A A  ← 最終的な実効アドレス
    -----------------------

ESA と ELA の選択

ESA レコードは、10 バイトという細かい単位でアドレスを指定できますが、100000h 以上の大きなアドレスを表現できません。これに対して、ELA レコードは、大きなアドレスでも表現できますが、10000h 単位でしかアドレスを指定できません。したがって、セグメント アドレスの表現に使用されるアドレス レコードは、一意に決まる場合があります。

しかし、ESA レコードと ELA レコードのどちらでも表現できるセグメント アドレスもあります。たとえば、70000h というセグメント アドレスは、ESA レコード値の 7000h で表すことも、ELA レコード値の 0007h で表すこともできます。

lil の場合、デフォルトでは ESA レコードが使用され、ESA レコードだけで表現できない場合にのみ ELA レコードが使用されます。つまり、ESA レコードですべての配置アドレスを表現できるならば、ELA レコードは生成されません。

ただし、lil のオプション /RL を指定すると、ELA レコードが優先的に使用されます。

インテル HEX 形式ファイルの例

次は HEX ファイルの一例です。見やすいようにスペースを入れてありますが、実際の HEX ファイルでは 16 進数が連続して並んでいます。

:02 0000 02 2000 DC
:10 0000 00 B870178ED8BB2000C607AAEA00000120 EE
:02 0000 02 2001 DB
:0E 0000 00 43C607BBC6063412CCEA01008813 C3
:02 0000 02 1388 61
:04 0000 00 909090F4 58
:02 0000 02 1770 75
:04 0020 00 01020304 D2
:04 0000 03 20000000 D9
:00 0000 01 FF

次は、上の HEX ファイルのソースコードです。

assume cs:code
code segment
start: mov ax, seg data
mov ds, ax
mov bx, offset d1
mov byte ptr [bx], 0AAh
jmp far ptr step2
code ends

assume cs:code2
code2 segment
step2: inc bx
mov byte ptr [bx], 0BBh
mov byte ptr ds:[1234h], 0CCh
jmp far ptr step3
code2 ends

assume cs:code3
code3 segment at 5000
nop
step3: nop
nop
hlt
code3 ends

data segment at 6000
org 20h
d1 db 1,2,3,4
data ends

end start

アセンブル、リンク方法は次のとおりです。

lasm sample.asm
lil -hex -scode=2000 sample.obj


デバッグ情報ファイル

Light C 1.1 以降または Light Macro Assembler 2.2 以降で /zh を指定してコンパイルまたはアセンブルすると、テキスト形式の dbg ファイルが生成されます。この dbg ファイルには、ソース行や各種ラベルと実行イメージ (hex、exe、com など) との対応関係が記載されます。

この機能は、特定の他社のデバッガと共に使用するために追加されたものなので、2005/10 現在、一般ユーザーの方には関係ありません。ただ、この情報を利用する独自のツールを作ることなどは考えられます。

  • デバッグ情報ファイルは「レコード」の連続です。各レコードは改行 (0D0Ah) で区切られます。
  • レコードは「フィールド」の連続です。各フィールドはタブ (09h) で区切られます。
  • フィールドは、「フィールド名」、コロン (:)、および「値」から構成されます。
  • 一部の値は数値を表します。数値は 10 進数か 16 進数で、16 進数の場合は先頭に「0x」が付きます。
  • 先頭がセミコロン (;) の行は、コメントです。

例

次は、Light C for x86 に付属のサンプル プログラム prime.c を /zh でコンパイルしたときに生成されるデバッグ情報ファイルの一例です。

; Debug Information File for LASM/Light C
VER	V:1
FILE	L:23	F:prime.c
N	L:6	A:0xC
N	L:7	A:0x11
N	L:8	A:0x16
N	L:9	A:0x18
N	L:10	A:0x1D
N	L:11	A:0x1F
N	L:12	A:0x27
N	L:13	A:0x34
N	L:14	A:0x37
N	L:16	A:0x39
N	L:18	A:0x45
N	L:10	A:0x48
N	L:20	A:0x4A
N	L:8	A:0x4D
N	L:22	A:0x53
N	L:23	A:0x5D
GS	S:a1?	T:A[4].I1	A:0x0	C:FS,TMP
GS	S:a2?	T:A[2].I1	A:0x4	C:FS,TMP
PROC	S:_main	T:C	A:0x0	B:0x63	ZA:0	ZC:2	ZL:6
LS	S:found$	T:I2	O:-6
LS	S:trg$	T:I2	O:-4
LS	S:dvsr$	T:I2	O:-2
GS	S:top_1	T:C	A:0x18
GS	S:top_2	T:C	A:0x1F
GS	S:els_3	T:C	A:0x39
GS	S:ent_2	T:C	A:0x48
GS	S:bot_2	T:C	A:0x4A
GS	S:ent_1	T:C	A:0x4D

参照

  • レコード
  • タイプ
  • 属性とラベル


レコード

デバッグ情報ファイルすべてのレコードを説明します。

VER V:num

デバッグ情報ファイルのバージョン番号で、2000/01 現在、num は「1」です。このレコードは、デバッグ情報ファイルの先頭に 1 つだけ出力されます。

例 VER V:1

FILE L:num F:fname

ソース ファイルを示します。num はソース ファイルの全行数、fname はファイル名またはパス名です。これ以降の N、PROC、GS、LS などの各レコードで示される項目は、このファイルに属します。 99/12 現在、インクルード ファイル内の行番号情報は出力されないため、このレコードはファイルに 1 つしか出力されません。

例 FILE L:23 F:prime.c

N L:num A:addr

ソース コード行と実行イメージ アドレスの対応を示します。num は、直前の FILE レコードで示されたソース ファイルの行番号 (1 ベース) です。addr は、対応する絶対アドレスです。

例 N L:10 A:0x48

PROC S:name T:C A:addr B:end-addr C:attr-str
ZA:arg-sz ZC:cod-sz ZL:loc-sz

プロシージャ (関数) と実行イメージ アドレスの対応を示します。name はプロシージャ名、addr はプロシージャ先頭の絶対アドレス、end-addr は末尾の絶対アドレス (このプロシージャに属さない最初のアドレス) です。オプションの C:attr-str は、追加属性を通知します。

arg-sz、cod-sz、loc-sz は、それぞれスタックに積まれた引数、リターン アドレス、およびローカル変数のサイズを示します。これらの情報は、関数のコール スタックを解析するときに役立ちます。

これ以降の LS レコードで示されるローカル変数と、TMP 属性の GS レコードで示される静的変数は、このプロシージャに属します。

例 PROC S:_main T:C A:0x0 B:0x63

GS S:name T:type A:addr C:attr-str

グローバル ラベル (変数) と実行イメージ アドレスの対応を示します。name はラベル名、type はそのラベルのタイプ (型)、addr は対応する絶対アドレスです。C:attr-str は省略される場合もあり、各種の追加属性を通知します。

例 GS S:a2? T:A[2].I1 A:0x4 C:FS,TMP

LS S:name T:type O:offs C:attr-str

スタック上のローカル ラベルと実行イメージ アドレスの対応を示します。プロシージャへの引数もこのレコードで示されます。offs はレジスタ BP 相対オフセットで、正負に応じて先頭に「+」か「-」が付きます。引数では正、ローカル変数では負になります。ほかのフィールドは GS レコードと同じです。

例 LS S:found$ T:I2 O:-6

SUTAG S:tag-name

構造体または共用体の型定義を開始します。tag-name はタグ名 (型名) です。SUTAG レコードの後には 0 以上の _FLD レコードが続き、最後に SUEND レコードが置かれます。これらで 1 つの構造体または共用体を定義します。

SUTAG レコードで定義されたタグ名は、後続の GS、LS、または _FLD レコードの T フィールドの値で使用されます (T:T[tag_name])。

次は、Light C の stdio.h で定義されている _FILE 構造体を表すデバッグ情報です。

例
SUTAG S:_FILE
_FLD S:hdl T:U2 O:0
_FLD S:flags T:I2 O:2
_FLD S:bufsz T:U2 O:4
_FLD S:vlen T:U2 O:6
_FLD S:idx T:U2 O:8
_FLD S:buffer T:P2.I1 O:10
_FLD S:link T:P2.S[_FILE] O:12 ← 自己参照
_FLD S:pos T:I4 O:14
_FLD S:fname T:A[14].I1 O:18
SUEND O:32

_FLD S:name T:type O:offs B:bit-offs Z:bit-size

構造体または共用体のメンバを示します。name はメンバ名、type はそのタイプ、offs はメンバのオフセットです。共用体の場合は、すべてのメンバで offs が 0 になります。

ビットフィールドでは、B および Z フィールドが出力されます。B フィールドはオフセット (最下位ビットの位置) を示し、Z フィールドはビットサイズを示します。次の例をご覧ください。

ソースコード例
struct st_t
{ int a:2;
int b:3;
int c:4;
int d:1;
};

そのデバッグ情報例
SUTAG S:st_t
_FLD S:a T:I2 O:0 B:0 Z:2
_FLD S:b T:I2 O:0 B:2 Z:3
_FLD S:c T:I2 O:0 B:5 Z:4
_FLD S:d T:I2 O:0 B:9 Z:1
SUEND O:2

SUEND O:offs

構造体または共用体の型定義を終了します。offs は終端のオフセット、つまり構造体/共用体のサイズです。


タイプ

GS、LS、_FLD、および PROC レコードの T フィールドは、ラベルのタイプ (変数の型) を示します。T フィールドの値は、次のいずれかです。

値 | 例 | 意味
C | C | コード ラベル
Xn | X1, X2, X4, X100 | 型が不明の n バイトデータ (n >= 0)
In | I1, I2, I4 | 符号付き n バイト整数
Un | U1, U2, U4 | 符号なし n バイト整数
F4 | F4 | 4 バイト IEEE 浮動小数点数
F8 | F8 | 8 バイト IEEE 浮動小数点数
P2.type | P2, P2.I1, P2.P2.I1 | type 型への 2 バイト (near) ポインタ
P4.type | P4, P4.A[12].I[1] | type 型への 4 バイト (far) ポインタ
A[n].type | A[4].I2 | n 個の type 型の値の配列
T[tag-name] | T[_FILE] | tag で示される構造体または共用体

例 1

char c; | → | T:I1
unsigned short u; | → | T:U2
long l; | → | T:I4
char* ptr; | → | T:P2.I1
char** pp; | → | T:P2.P2.I1
char far* fptr; | → | T:P4.I1
char far** fpp; | → | T:P2.P4.I1
void* pv; | → | T:P2.X0
int ar1[10]; | → | T:A[10].I2
int* ar2[10]; | → | T:A[10].P2.I2
int (*ar3)[10]; | → | T:P2.A[10].I2
int aaa[5][7][9]; | → | T:A[5].A[7].A[9].I2

例 2

ソースコード

struct {int a; int b;}* sptr;

そのデバッグ情報

SUTAG	S:s1?
_FLD	S:a	T:I2	O:0
_FLD	S:b	T:I2	O:2
SUEND	O:4
GS	S:_sptr  T:P2.S[s1?]  A:0xC3B


属性とラベル

属性

GS、LS、PROC レコードの C フィールドは、各種の追加属性を示します。各属性はカンマ (,) で区切られます。次の属性があります。

値 | 意味
TMP | コンパイラが生成した内部ラベル。
FS | ファイル外に公開されない静的ラベル。C 言語の static 変数には、この属性が付加されます。
SI | レジスタ変数。LS レコードで使用され、このローカル変数がレジスタ変数として si で実現されていることを示します。この場合、オフセットを示す O フィールドは、常に +0 になります。
DI | レジスタ変数。si ではなく di によるレジスタ変数であることの除き、SI 属性と同じです。

ラベル

Light C で生成されたラベルには、その性格に応じて「_」「$」「?」が付加されます。

  • ファイルの外部に公開されるグローバル ラベルは、先頭に「_」が付加されます。
  • ファイルの外部に公開されない静的ラベル、ローカル ラベル、および引数は、末尾に「$」が付加されます。複数の同名ラベルがある場合は、さらに「2」「3」などの番号が付きます。
  • for、while などのループから、「top_1」「ent_2」などの内部コード ラベルが生成されます。
  • 内部生成された変数名の末尾には「?」が付きます。


IEEE 浮動小数点数の形式

Light C では小数を IEEE (Institute of Electrical and Electronic Engineers) の浮動小数点数形式で表します。この形式は世界で広く使用されている標準です。

IEEE 浮動小数点数は、符号部、指数部、仮数部の 3 つの部分から構成されます。符号部は数値の正負を表し、2<指数>×<仮数> が数値の絶対値を表します。

  • 符号部 － 最上位ビット (最上位バイトの最上位の 1 ビット) は符号ビットです。0 ならば正、1 ならば負を表します。
  • 指数部 － <指数> + <バイアス> の値を持ちます。バイアスは下の表に示されている定数で、指数部の最大値の約半分です。バイアスの存在により、負の指数も表すことができます。
  • 仮数部 － 通常、仮数部の最上位ビットは 1 になります。言い換えると、そうなるまで指数値が減らされています (正規化)。実際の 4 バイト浮動小数点数と 8 バイト浮動小数点数では、この最上位ビットは省略されます。

例外として、浮動小数点数の値が 0.0 の場合は、符号部、指数部、仮数部のすべてのビットが 0 になります。また、IEEE の仕様では正負の無限大や非数 (NaN) を表す形式も定義されていますが、Light C はこれらを使用しないため、説明も省略します。

主な IEEE 浮動小数点数として、4 バイト、8 バイト、10 バイトの形式を示します。C 言語の float は 4 バイト、double は 8 バイトの形式になります。また、Light C の浮動小数点数演算ライブラリの内部では、10 バイト形式を使って演算が行われます。

 | 4 バイト | 8 バイト | 10 バイト
総計ビット数 | 32 | 64 | 80
符号ビット数 | 1 (31) | 1 (63) | 1 (79)
指数ビット数 | 8 (30～23) | 11 (62～52) | 15 (78～64)
仮数ビット数 | 23 (22～0) | 52 (51～0) | 64 (63～0)
バイアス | 0x7F | 0x3FF | 0x3FFF

※( ) 内の数値はビット範囲

絶対値の計算方法を示します。

種類 | 絶対値
4 バイト形式 | (2<指数部> - 0x7F) × (1 + <仮数部> / 0x80,0000)
8 バイト形式 | (2<指数部> - 0x3FF) × (1 + <仮数部> / 0x10,0000,0000,0000)
10 バイト形式 | (2<指数部> - 0x3FFF) × (<仮数部> / 0x8000,0000,0000,0000)

Light C でのいくつかの例を示します。

数値 | 4 バイト形式 | 8 バイト形式
0.0 | 0x00000000 | 0x0000000000000000
1.0 | 0x3F800000 | 0x3FF0000000000000
-1.0 | 0xBF800000 | 0xBFF0000000000000
2.0 | 0x40000000 | 0x4000000000000000
3.14 | 0x4048F5C3 | 0x40091EB851EB851F
10 | 0x41200000 | 0x4024000000000000
100 | 0x42C80000 | 0x4059000000000000
1000 | 0x447A0000 | 0x408F400000000000


メモリ モデル

Light C では、次の 4 つのメモリ モデルを使用できます。

名前 | オプション | データの制限 | コードの制限
small | -as (既定値) | 64 KB まで (near) | 64 KB まで (near)
medium | -am | 64 KB まで (near) | 無制限 (far)
compact | -ac | 無制限 (far) | 64 KB まで (near)
large | -al | 無制限 (far) | 無制限 (far)

これらのメモリ モデルに対応して、4 種類のライブラリ関数が用意されています。

データへの標準的なポインタは、small および medium モデルでは near、compact および large モデルでは far になります。コードへの標準的なポインタは、small および compact モデルでは near、medium および large モデルでは far になります。ポインタの種類を明示的に指定するには、キーワード near (_near) および far (_far) を使用します。

near データと far データ

ライブラリ関数は、(特に明記されている場合を除き) 標準サイズのポインタを受け取ります。キーワード far を使って定義したデータは、標準ライブラリ関数には渡せない場合があるので注意してください。次に例を示します。
static char far buf[1000];
strcpy( buf, "string" );

このコードを small または medium モデルでコンパイルすると、警告が発生し、正しいコードは生成されません。buf は 4 バイトの far アドレスを表しますが、small および medium モデルの strcpy 関数は 2 バイトの near アドレスしか受け取れません。

この場合は、far データ用の _fstrcpy 関数を使用します。よく使用される関数には、このように far データ用のバージョンが用意されています。
static char far buf[1000];
_fstrcpy( buf, "string" );

near アドレスの "string" は、_fstrcpy に渡すために自動的に far アドレスに変換されます。

near を使って定義したデータを compact または large モデルの標準ライブラリ関数に渡す場合は、問題は生じません。この場合は、near アドレスが自動的に far アドレスに変換されます。

near コードと far コード

far メモリに置かれた関数から、near メモリに置かれた関数を呼び出すことはできません。far 関数から near 関数を呼び出すと、共通のフレームを持たないラベルへの相対ジャンプが行われたことを示すアセンブラの警告が表示されます。

これに対して、near メモリに置かれた関数から far メモリに置かれた関数を呼び出すことは可能です。
void near func1();
void far func2();
void near func10() {
func1(); | // 可能
func2(); | // 可能
}
void far func20() {
func1(); | // 不可能
func2(); | // 可能
}


セグメント名

C 言語の中では、セグメントの名前を意識する必要はありません。しかし、アセンブラなどで記述した別のルーチンとリンクしたり、ROM 化ソフトウェアでセグメントごとにロード アドレスを指定する場合には、セグメント名が関係します。

生成されたコードは、次のセグメントに置かれます。

セグメント名 | コンバイン | クラス | 備考
cseg | public | CODE | near コード
kseg | public | CONST | near 定数データ
dseg | public | DATA | near データ
bseg | public | BSS | 初期化されないファイル内 near データ
c_common | public | BSS | 初期化されない共有 near データ
sseg | stack | STACK | スタック領域
cseg_fname | private | FAR_CODE | far コード
kseg_fname | private | FAR_CONST | far 定数データ
dseg_fname | private | FAR_DATA | far データ
bseg_fname | private | FAR_BSS | 初期化されないファイル内 far データ
FAR_BSS | private | FAR_BSS | 初期化されない共有 far データ

上の表で、fname はソース ファイル名です。

例 (small モデルの場合)

int func() { } | // → cseg
const char csd[] = "123"; | // → kseg
char data[] = "123"; | // → dseg
static int bss; | // → bseg
int common; | // → c_common
int far ffunc() { } | // → cseg_fname
const char far fcsd[] = "123"; | // → kseg_fname
char far fdata[] = "123"; | // → dseg_fname
static int far fbss; | // → bseg_fname
int far fcommon; | // → FAR_BSS

near データ用のセグメント (kseg、dseg、bseg、c_common、sseg) は、いずれもグループ DGROUP に属します。コードの実行中、DGROUP の位置は ds レジスタによって示されます。

セグメント名の変更

オプション -segn および -segc を使用すると、上のセグメント名とセグメント クラス名を変更できます。#pragma segment を使用して、ファイル内の一部のコードについてのみ、セグメント名およびセグメント クラス名を変更することもできます。

セグメント名を変更したプログラムをライブラリ関数とリンクする場合は、作成したプログラムが使用するセグメント名と、ライブラリ関数で使用されているセグメント名との整合性に注意してください。たとえば、small モデルでコード セグメントの名前を「cseg」以外に変更すると、そのセグメントからライブラリ関数を呼び出すことはできなくなります。

ライブラリのソース コードを変更して、他のセグメント名を使用することもできます。その場合は、common.inc ファイルを編集する必要があります。


関数呼び出し規約

Light C で作成した関数をアセンブラなどの他言語のルーチンとリンクする場合は、関数の呼び出し規約を合わせる必要があります。ここでは、Light C で使用される呼び出し規約について説明します。

なお、実際の正確な呼び出し規約を確認するには、-fa で生成されるアセンブラ コードを調べると効果的です。次は、C のソース ファイルと、そこから生成されたアセンブラ コードの例です。

// C のソース
int subr( int a, char b, long c ) {
    a = 1;
    b = 1;
    c = 1;
    return( 4 );
}
; アセンブラ コード
public _subr
_subr proc near ; line 1
push bp
mov bp,sp
mov ax,0
call __stack_chk
a$ equ [bp+4] ; size=2
b$ equ [bp+6] ; size=1
c$ equ [bp+8] ; size=4
mov word ptr [a$],1h ; line 3
mov byte ptr [b$],1h ; line 4
mov word ptr [c$],1h ; line 5
mov word ptr [c$+2],0h
mov ax,4h ; line 6
mov sp,bp
pop bp
ret
_subr endp

「アセンブラ ルーチンとのリンク」も参照してください。

引数

Light C では、すべての引数がスタック経由で関数に渡されます。 引数は 2 バイト単位でスタックに置かれます。つまり、1 バイトの char 変数は 2 バイト、3 バイトの構造体は 4 バイトのスタック領域を占有します。

関数内では、通常、BP レジスタを使ってスタック上の引数にアクセスします。

戻り値

戻り値は、サイズに応じてレジスタまたはスタック経由で返されます。次のようになります。

型 | サイズ | 返される方法
char | 1 | AL レジスタ経由
int | 2 | AX レジスタ経由
long | 4 | DX:AX レジスタ経由
float | 4 | DX:AX レジスタ経由
double | 8 | スタック経由
near ポインタ | 2 | AX レジスタ経由
far ポインタ | 4 | DX:AX レジスタ経由
構造体 | 1 | AL レジスタ経由
構造体 | 2 | AX レジスタ経由
構造体 | 4 | DX:AX レジスタ経由
構造体 | 3, 5～ | スタック経由

引数の順序とアンダースコア (_)

関数には、関数名と引数の順序を指定するために、次の修飾子を指定できます。

修飾子 | 「_」の付加 | スタックに引数を積む順序
(なし) | あり | 後から
syscall | なし | 後から
stdcall | あり | 前から
pascal | なし | 前から
cdecl_r | あり | 後から
syscall_r | なし | 後から
stdcall_r | あり | 前から
pascal_r | なし | 前から

これらは、API などの特殊な関数を宣言する場合、または特殊なルーチンから呼び出される関数を定義する場合に指定します。
例 | int syscall funcA(int a1, int a2); | // プロトタイプ宣言で
 | void pascal funcB(int a1, int a2) { | // 関数定義で
 | ...
 | }

引数が前からスタックに積まれる stdcall および pascal では、関数の呼び出し側ではなく、関数側がスタックから引数を除去します。

V1.42 以降では、引数を除去する側だけを逆にする cdecl_r、syscall_r、stdcall_r、pascal_r が追加されました。

interrupt 修飾子については、「割り込みハンドラ」を参照してください。


割り込みハンドラ

interrupt 修飾子を指定することにより、プロセッサ割り込みによって呼び出される関数を定義できます。
例 | #include <stdio.h>
 | #include <dos.h>
 | void interrupt handler( void ) {
 | printf( "ハンドラが呼び出されました\n" );
 | }
 | int main() {
 | setvect( 0x40, handler );
 | union REGS regs;
 | int86( 0x40, &regs, &regs ); | // ハンドラの呼び出し
 | handler(); | // 直接呼び出すこともできます
 | return( 0 );
 | }

interrupt 関数は、ret 命令ではなく iret 命令で帰還します。また、interrupt 関数の先頭で AX, CX, DX, BX, SP, BP, SI, DI ES, DS の各レジスタが順にスタックへプッシュされ、末尾で DS, ES, DI, SI, BP, SP, BX, DX, CX, AX が順にポップされます。AX レジスタが必ず保存されるため、interrupt 関数から値を返すことはできません。その他は通常の関数と同じです。

interrupt 関数を直接呼び出すこともできます。この場合は、pushf 命令が call 命令の前に付加されます。medium/large モデルでは、push cs 命令も付加されます。

large 以外のメモリ モデルでは、interrupt 関数に制御が渡されたときの cs および ds レジスタの値に注意してください。たとえば、上のコードでは interrupt 関数内で printf を呼び出しているため、small/compact モデルの場合は cs レジスタの値が重要です。また、small/medium モデルの場合は、メッセージ文字列に正しくアクセスできるように ds レジスタを既定値に維持する必要があります。


コンパイル エラーと警告

C.1000 ～ | コンパイル エラー。1000 番台のエラーが発生するか、-errmax で指定された数のエラーが発生すると、コンパイルが中止されます。オブジェクト ファイルは生成されません。
C.5000 ～ | 警告。コンパイルは続行され、オブジェクト ファイルが生成されますが、作成したプログラムが正しく動作しない可能性もあります。
C.8000 ～ | 確認。正当な構文ですが、確認のためメッセージを表示します。
A.xxxx | アセンブル エラーおよび警告。通常、このエラーは発生しませんが、インライン アセンブラの構文に誤りがあった場合などに、内部アセンブラ lcasm.exe から出力されます。
L.xxxx | リンカ エラーおよび警告。リンク時に lil32.exe が出力したメッセージです。

参照

  • エラー、警告、デバッグ オプション
  • ランタイム エラー


ランタイム エラー

作成したプログラムを実行したときに、以下のエラー メッセージが表示される場合があります。

R.1000 null pointer assignment

プログラムのどこかで NULL ポインタの参照先に誤ってデータを書き込んだことを示します。このランタイム エラーは、プログラムの誤りを発見しやすくする目的で用意されています。

Light C で作成したプログラムでは、DGROUP の先頭に置かれる定数データ セグメント kseg の先頭に、_null_area という 4 バイトのデータが自動的に確保されます。main() 関数の終了後にこの領域がチェックされ、初期値と異なる値が設定されていると、このランタイム エラーが発生します。この場合は、NULL 値を持つ near ポインタの参照先に対して、言い換えれば ds:0000h に対して、書き込みが行われた可能性が高いと考えられます。

このチェックは、既定では main() 関数の終了後に、既定のスタートアップ ルーチン start.asm で行われます。プログラムの任意の場所で、_nullptr_chk() を呼び出してチェックを行うこともできます。

_nullptr_chk() は、エラーを検出すると raise( _SIGNULLPTR ) を呼び出します。signal を使用すれば、独自のハンドラ関数を定義できます。 この検査は、near ポインタについてのみ有効です。

R.1010 stack overflow

オプション -gs を指定しない限り、スタック オーバーフローを検出するために、各関数の先頭にスタック ポインタの値を検査するコードが挿入されます。

このランタイム エラーが発生した場合は、関数呼び出しの入れ子レベルが多いか、局所変数のサイズが大きいために、スタックが不足しています。または、関数が無限に再帰的に呼び出されています。

スタック検査は、_stack_chk() 関数で行われます。ライブラリ関数内ではスタック チェックが行われないため、ライブラリ関数が使用するスタックも顧慮して、スタックの残りサイズが約 700 バイトになるとエラーと判定します。ライブラリ ソース signal.c で _stack_chk() の定義を書き換えれば、この動作を変更できます。

スタック サイズの既定値は 4096 バイトで、ライブラリ ソース start.asm で定義されています。スタックを拡大するには、オプション -stk を使用するか、start.asm を書き換えます。_rest_stack() または _min_stack() を使用すると、残存スタック サイズを取得できます。

_stack_chk() は、エラーを検出すると raise( _SIGSTKOVER ) を呼び出します。既定の _SIGSTKOVER ハンドラは、メッセージを表示してプログラムを中止します。signal で独自のハンドラ関数を定義することもできます。-os:none を指定した場合は、既定の raise( _SIGSTKOVER ) が何も行わないので注意してください。

メモ small/compact メモリ モデルで定義した far 関数には、スタック検査コードは挿入されません。

R.1100 abnormal termination

abort() 関数が呼び出されたため、プログラムを中断しました。


ISO/JIS/ANSI 規格との互換性

ISO/JIS/ANSI 規格からの拡張

日本語表記

Light C では、変数名、関数名、マクロ名などすべての識別子に Shift-JIS コードの日本語文字を使用できます。

文字列内を除き、全角のアルファベットと、＋、－、［］などの記号は、半角と同一視されます。したがって、キーワードや演算子を全角で記述することもできます。
例 | if ( 金額 >= 100000 )
 | 資産 += 金額;
 | else
 | 経費 += 金額;

キーワード

次のキーワードは、ISO/JIS/ANSI 規格外です。
near far syscall stdcall pascal interrupt

これらのキーワードには、先頭に下線 (_) を付けることもできます。下線を付けたキーワードは、-ansi を指定したときでも使用できます。

変数宣言、コメント

次の C99/C++ 互換仕様も、C89 仕様では ISO/JIS/ANSI 規格外です。

  • コードの途中で変数を宣言する
  • for 文の初期化式で変数を宣言する
  • // でコメントを始める
例 | for ( int i = 0; i < 10; i++ )
 | sprintf( buf, "i = %d\n", i ); | // コメント...
 | long x;

-ansi を指定すると、ISO/JIS/ANSI 規格からの拡張が無効になります。

サポートされない機能

以下の機能はサポートされていません。

  • 古いカーニハン リッチー (K&R) 形式の関数宣言
    int func( a, b )
    int a;
    long b;
    { ... }
  • ロケール

    ヘッダー ファイル locale.h と、そこに含まれる関数や定数は、サポートされていません。setlocale、strcoll、strxfrm 関数もサポートされていません。生成されるコードのサイズも考慮して、現時点では、ロケールの切り替えに対応する予定はありません。常に日本語と Shift-JIS コード体系が使用されます。

  • 一部のワイド文字関数


ROM 化

ROM 化するプログラムでは、コードやデータの位置を自由に制御したい場合があります。この場合は、コードやデータが所属するセグメントの位置を指定するリンカ オプション /S を使用します。必要ならば、-segn や #pragma segment を使って個々のデータの所属先セグメントを変更できます。

リンカ オプション /S で DGROUP 所属セグメント (dseg、kseg、sseg、bseg) の位置を指定する場合は、DGROUP の範囲が 64 KB を超えないように注意してください (超えるとリンク時に警告されます)。

「kseg を ROM 領域に、その他を RAM 領域に配置したいが、ROM 領域と RAM 領域が離れている」場合は、kseg も RAM 領域に配置しておき、スタートアップ ルーチンで最初に必要なデータを ROM から RAM に転送する方法があります。


スタートアップ ルーチン

ライブラリの start.obj モジュールは、MS-DOS 用のスタートアップ ルーチン (初期化コード) です。MS-DOS またはそれと互換性のある OS を使用しない場合、このスタートアップ ルーチンは使用できません。その場合は、独自のスタートアップ ルーチンを記述して、Light C で作成した関数を呼び出す前に次の状態を整える必要があります。

  • プログラムのエントリ ポイントとしてラベル「start」を公開する。
  • DGROUP のアドレスを ds および ss レジスタに設定する。
  • sp レジスタにスタック領域の上限オフセットを設定する。
  • FLAGS レジスタの方向フラグ DF を cld 命令などでクリアする。これは、ライブラリ関数 memcpy などで 8086 ストリング命令が使用されるためです。
  • FPU を使用する場合は、finit 命令で FPU を初期化する。
  • small/medium モデルで malloc などのメモリ割り当て関数を使用する場合は、size_t 型の広域変数 __heap_top および __heap_bot に、near ヒープの先頭および末尾を示す DGROUP 相対オフセットを設定する。

ライブラリのソース コード start.asm も参考にしてください。


アセンブラ ルーチンとのリンク

Light C で作成したコードをアセンブラ ルーチンとリンクする場合は、以下の点に注意してください。なお、-fa または -fl を指定してアセンブラ コードを生成し、必要な箇所だけを変更すれば、容易に整合性を保つことができます。

スタートアップ ルーチン

プログラムのエントリ ポイントをアセンブラで作成し、アセンブラ ルーチンから C 関数を呼び出す場合は、あらかじめスタートアップ ルーチンを実行しておく必要があります。

セグメント名

セグメント定義とグループの整合性に注意してください。

near コード呼び出しと far コード呼び出し

アセンブラ ルーチンから C 関数を呼び出す場合、RETN (near リターン) 命令で帰還する関数は near CALL で、RETF (far リターン) 命令で帰還する関数は far CALL で呼び出す必要があります。RETF 命令は、small/compact モデルで far を指定した関数と、medium/large モデルで near を指定しなかった関数で使用されます。

//---- C コード ----
void near nfunc() { }
void far ffunc() { }

;---- アセンブラ コード ----
call near ptr nfunc		; OK
call near ptr ffunc		; Error
call far ptr ffunc		; Error
call far ptr ffunc		; OK

C 関数からアセンブラ ルーチンを呼び出す場合も、同様に near と far を合わせる必要があります。

;---- アセンブラ コード ----
_nfunc	proc	near
    ret			; RETN コードが生成される
_nfunc	endp
_ffunc	proc	far
    ret			; RETF コードが生成される
_ffunc	endp

//---- C コード ----
void near nfunc( void );	// near 関数として宣言
void far ffunc( void ); 	// far 関数として宣言
void main( void ) {
    nfunc();		// OK (near CALL コードが生成される)
    ffunc();		// OK (far CALL コードが生成される)
}

引数の受け渡し

Light C が生成した関数は、すべての引数をスタック経由で受け取ります。通常、引数は後ろから順にスタックに積まれますが、この順番は変更できます。 char 型の引数は、常に int 型に変換されます。

関数から戻ったら、スタックに積んだ引数のサイズに合わせて、スタック ポインタ sp の値を増加する必要があります。この操作を「スタックから引数を取り除く」と表現する場合があります。

//---- C コード ----
void func( short, long );

;---- アセンブラ コード ----

push	word ptr [arg2+2]	; long 値の上位半分
push	word ptr [arg2]	; long 値の下位半分

push	word ptr [arg1]	; short 値
call	_func
add	sp, 2+4		; スタックを復元

なお、アセンブラ側では、PROC 文、INVOKE 文など利用して引数の定義を簡略化できます (LASM の場合)。

戻り値の受け渡し

戻り値は、サイズに応じて次の方法で返されます。

バイト数 | 方法
1 | AL レジスタ
2 | AX レジスタ
3 | スタック
4 | DX:AX レジスタ ペア (DX が上位)
5 バイト以上 | スタック

構造体や double 値を返すときなど、戻り値が 5 バイト以上または 3 バイトになる場合があります。この場合は、戻り値を受け取るデータ域のアドレスを最後にスタックします。

//---- C コード ----
double func( short, long );

;---- アセンブラ コード ----
push	word ptr [arg2+2]	; long 値の上位半分
push	word ptr [arg2]	; long 値の下位半分

push	word ptr [arg1]	; short 値
push	bx			; 戻り値を受け取る領域のアドレスを積む
call	_func
add	sp, 2+2+4		; スタックを復元

この例では、ds:bx で示されるメモリに 8 バイトの double 値が書き込まれます。

戻り値を受け取る領域のアドレスは、メモリ モデルにかかわりなく、常に ds (DGROUP) からの相対オフセットで指定します。

レジスタの保存

C 関数から呼び出されるアセンブラ ルーチンでは、SI、DI など、特定のレジスタの値を不変に保つ必要があります。

レジスタ、フラグ | 渡される値 | 値の保存が必要か
AX、DX | 不定 | 不要 (必要に応じて戻り値を設定する)
BX、CX | 不定 | 不要
SI、DI | 不定 | 必要
BP | 呼び出し側のフレーム | 必要
DS | near データ セグメント群のグループ アドレス (DGROUP) | 必要
ES | 不定 | 不要
SS | スタック セグメント | 必要

値を保存する必要があるレジスタを使用する場合は、値をいったんスタックなどに退避して、呼び出し側に戻る前に復元してください。

逆に、アセンブラ ルーチンから C 関数を呼び出す場合は、変更不可のレジスタの値が維持されることを前提としたコードを記述できます。

データ形式

  • char、int、long などの整数値は、通常の 2 の補数表現で表されます。
  • float および double は、IEEE 浮動小数点数形式で表されます。
  • near ポインタは、グループ DGROUP (= ds) からの 16 ビット オフセット値で表されます。
  • far ポインタは、32 ビットの絶対アドレスで表されます。上位 2 バイトにセグメント値、下位 2 バイトにオフセット値が格納されます。
  • 構造体のメンバは、-alignst の指定に従って配置されます。

参照

  • インライン アセンブラ
  • _asmcode
  • 関数呼び出し規約


他の高級言語とのリンク

Light C で作成したコードは、他の高級言語で作成したルーチンとリンクできます。その場合は、Light C の呼び出し規約と対象言語の呼び出し規約を両方とも考慮する必要があります。

Light C の呼び出し規約は、pascal キーワードなどを使ってさまざまに指定できますが、それでも対象言語の呼び出し規約との互換性を確保できない可能性があります。その場合は、アセンブラでインターフェイス用のルーチンを作成してください。

呼び出し規約の互換性については、「関数呼び出し規約」、「アセンブラ ルーチンとのリンク」、およびリンク対象言語のマニュアルを参照して判断してください。

このほか、オブジェクト ファイル形式の互換性の問題もあります。付属のリンカ LIL. が扱えるオブジェクト ファイルの範囲は比較的狭く、他の高級言語で作成したオブジェクト ファイルを認識できない可能性があります。しかし、Light C が生成するオブジェクト ファイルは標準性が高いため、他の高級言語に付属するリンカで読み込める可能性があります。


入出力先の変更

作成するプログラムを MS-DOS 以外の環境で実行する場合、ファイル入出力関数 (fopen、fwrite など) および標準入出力関数 (printf、scanf など) を使用することはできません。これらの関数は MS-DOS が提供する INT 21h ファンクションを使用するためです。

ただし、入出力先は変更できます。ファイルおよび標準入出力へのアクセスは、最後は必ずライブラリ モジュール file.asm および file2.asm で定義されている _read、_write、_open、_creat、_close、または _lseek ルーチンを通過します。したがって、これらを書き換えることにより、すべての入出力関数のアクセス先を一括して変更できます。

たとえば、_write 関数を再定義してデータを RS-232 ポートに送信すれば、printf 関数の出力が RS-232 ポートに送られます。


プログラムの最小化

プログラムのサイズを減らして高速化するには、次の方法が考えられます。

  • 最適化 → -o
  • スタック チェックの省略 → -gs
  • 文字列のプール → -gf
  • ターゲット CPU の適切な選択 → -8086、-186
  • small または medium モデルを使用する

プログラムのデータが多くて small または medium モデルに収まらない場合でも、compact/large モデルを使用するよりは、small/medium モデルを使って必要なときにのみ far を指定する方が効率的です。compact および large モデルでは、すべてのデータが既定で far になるため、かなりの負荷がかかります。

start.asm の編集

浮動小数点演算、clock()、malloc() などを使用しないプログラムでは、start.asm から特定の部分を削除することにより、余計なモジュールのリンクを防ぐことができます。

sprintf.c と sscanf.c の編集

printf または scanf 系の関数を使用する場合、浮動小数点演算やワイド文字列などを使用しないときは、ライブラリの sprintf.c および sscanf.c の先頭にあるスイッチを切り替えて、コードを削減できます。


互換プロセッサに関するメモ

AND、OR、XOR 命令で符号拡張ビットを使用してはならないプロセッサ

Light C の生成するコードは、AND、OR、XOR で符号拡張ビット (サインワード) を使用しません。つまり、Light Macro Assembler でオプション -se を指定した場合と同じコードが既定で生成されます。

浮動小数点演算レジスタが 1 本だけのシステム

8086 系のシステムには、ST(0) ～ ST(7) の 8 本の浮動小数点演算レジスタがありますが、Light C の生成するコードはスタック トップの ST(0) しか使用しません。したがって、浮動小数点演算レジスタを 1 本しか持たない 8086 互換システムでも問題は生じません。


こんなときは . . .

コンパイル エラー メッセージが読み取れない

エラー メッセージがスクロールして読み取れない場合は、次のようにしてください。

  • メッセージをファイルにリダイレクトする。
    例 lc sample.c > error.log
  • -errmax または -errcon を指定する。

作成したプログラムが不安定

次の可能性は考えられないでしょうか。

  • スタックがオーバーフローしていないか (→ R.1010 stack overflow)
  • 寿命の切れた局所変数を使用していないか

コンパイラの「内部エラー」が発生した

問題が再現するコードを電子メール等でお送りくだされば、早急に対応いたします。


アスキー/シフト JIS キャラクタ コード表

 | 00 | 10 | 20 | 30 | 40 | 50 | 60 | 70 | 80 | 90 | A0 | B0 | C0 | D0 | E0 | F0
0 | NUL |  | 空 | 0 |  | P |  | p |  | 全 | 空 | ｰ | ﾀ | ﾐ | 全 | 全
1 |  |  | ! | 1 | A | Q | a | q | 全 | 全 | ｡ | ｱ | ﾁ | ﾑ | 全 | 全
2 |  |  | " | 2 | B | R | b | r | 全 | 全 | ｢ | ｲ | ﾂ | ﾒ | 全 | 全
3 |  |  | # | 3 | C | S | c | s | 全 | 全 | ｣ | ｳ | ﾃ | ﾓ | 全 | 全
4 |  |  | $ | 4 | D | T | d | t | 全 | 全 | ､ | ｴ | ﾄ | ﾔ | 全 | 全
5 |  |  | % | 5 | E | U | e | u | 全 | 全 | ･ | ｵ | ﾅ | ﾕ | 全 | 全
6 |  |  | & | 6 | F | V | f | v | 全 | 全 | ｦ | ｶ | ﾆ | ﾖ | 全 | 全
7 | BEL |  | ' | 7 | G | W | g | w | 全 | 全 | ｧ | ｷ | ﾇ | ﾗ | 全 | 全
8 | BS |  | ( | 8 | H | X | h | x | 全 | 全 | ｨ | ｸ | ﾈ | ﾘ | 全 | 全
9 | HT |  | ) | 9 | I | Y | i | y | 全 | 全 | ｩ | ｹ | ﾉ | ﾙ | 全 | 全
A | LF |  | * | : | J | Z | j | z | 全 | 全 | ｪ | ｺ | ﾊ | ﾚ | 全 | 全
B | VT | ESC | + | ; | K | [ | k | { | 全 | 全 | ｫ | ｻ | ﾋ | ﾛ | 全 | 全
C | FF | → | , | < | L | \ | l | | | 全 | 全 | ｬ | ｼ | ﾌ | ﾜ | 全 | 全
D | CR | ← | - | = | M | ] | m | } | 全 | 全 | ｭ | ｽ | ﾍ | ﾝ | 全 |
E |  | ↑ | . | > | N | ^ | n | ~ | 全 | 全 | ｮ | ｾ | ﾎ | ﾞ | 全 |
F |  | ↓ | / | ? | O | _ | o | DEL | 全 | 全 | ｯ | ｿ | ﾏ | ﾟ | 全 |

NUL － ヌル (\0)
BEL － ベル (\a)
BS － バック スペース
HT － 水平タブ (\t)
LF － ライン フィード・行送り (\n)
FF － フォーム フィード
VT － 垂直タブ
CR － キャリッジ リターン・復帰 (\r)
ESC － エスケープ
DEL － 削除
空 － スペース文字
全 － Shift-JIS 全角文字の第 1 バイト


欧文フォント キャラクタ コード表

 | 00 | 10 | 20 | 30 | 40 | 50 | 60 | 70 | 80 | 90 | A0 | B0 | C0 | D0 | E0 | F0
0 | NUL |  | 空 | 0 |  | P |  | p | € |  |  | ° | À | Ð | à | ð
1 |  |  | ! | 1 | A | Q | a | q |  | ‘ | ¡ | ± | Á | Ñ | á | ñ
2 |  |  | " | 2 | B | R | b | r | ‚ | ’ | ¢ | ² | Â | Ò | â | ò
3 |  |  | # | 3 | C | S | c | s | ƒ | “ | £ | ³ | Ã | Ó | ã | ó
4 |  |  | $ | 4 | D | T | d | t | „ | ” | ¤ | ´ | Ä | Ô | ä | ô
5 |  |  | % | 5 | E | U | e | u | … | • | ¥ | µ | Å | Õ | å | õ
6 |  |  | & | 6 | F | V | f | v | † | – | ¦ | ¶ | Æ | Ö | æ | ö
7 | BEL |  | ' | 7 | G | W | g | w | ‡ | — | § | · | Ç | × | ç | ÷
8 | BS |  | ( | 8 | H | X | h | x | ˆ | ˜ | ¨ | ¸ | È | Ø | è | ø
9 | HT |  | ) | 9 | I | Y | i | y | ‰ | ™ | © | ¹ | É | Ù | é | ù
A | LF |  | * | : | J | Z | j | z | Š | š | ª | º | Ê | Ú | ê | ú
B | VT | ESC | + | ; | K | [ | k | { | ‹ | › | « | » | Ë | Û | ë | û
C | FF | → | , | < | L | \ | l | | | Œ | œ | ¬ | ¼ | Ì | Ü | ì | ü
D | CR | ← | - | = | M | ] | m | } |  |  |  | ½ | Í | Ý | í | ý
E |  | ↑ | . | > | N | ^ | n | ~ | Ž | ž | ® | ¾ | Î | Þ | î | þ
F |  | ↓ | / | ? | O | _ | o | DEL |  | Ÿ | ¯ | ¿ | Ï | ß | ï | ÿ

NUL － ヌル (\0)
BEL － ベル (\a)
BS － バック スペース
HT － 水平タブ (\t)
LF － ライン フィード・行送り (\n)
FF － フォーム フィード
VT － 垂直タブ
CR － キャリッジ リターン・復帰 (\r)
ESC － エスケープ
DEL － 削除
空 － スペース文字


Symbol フォント キャラクタ コード表

 | 00 | 10 | 20 | 30 | 40 | 50 | 60 | 70 | 80 | 90 | A0 | B0 | C0 | D0 | E0 | F0
0 |  |  |  | 0 | @ | P | ` | p | € |  |  | ° | À | Ð | à | ð
1 |  |  | ! | 1 | A | Q | a | q |  | ‘ | ¡ | ± | Á | Ñ | á | ñ
2 |  |  | " | 2 | B | R | b | r | ‚ | ’ | ¢ | ² | Â | Ò | â | ò
3 |  |  | # | 3 | C | S | c | s | ƒ | “ | £ | ³ | Ã | Ó | ã | ó
4 |  |  | $ | 4 | D | T | d | t | „ | ” | ¤ | ´ | Ä | Ô | ä | ô
5 |  |  | % | 5 | E | U | e | u | … | • | ¥ | µ | Å | Õ | å | õ
6 |  |  | & | 6 | F | V | f | v | † | – | ¦ | ¶ | Æ | Ö | æ | ö
7 |  |  | ' | 7 | G | W | g | w | ‡ | — | § | · | Ç | × | ç | ÷
8 |  |  | ( | 8 | H | X | h | x | ˆ | ˜ | ¨ | ¸ | È | Ø | è | ø
9 |  |  | ) | 9 | I | Y | i | y | ‰ | ™ | © | ¹ | É | Ù | é | ù
A |  |  | * | : | J | Z | j | z | Š | š | ª | º | Ê | Ú | ê | ú
B |  |  | + | ; | K | [ | k | { | ‹ | › | « | » | Ë | Û | ë | û
C |  |  | , | < | L | \ | l | | | Œ | œ | ¬ | ¼ | Ì | Ü | ì | ü
D |  |  | - | = | M | ] | m | } |  |  |  | ½ | Í | Ý | í | ý
E |  |  | . | > | N | ^ | n | ~ | Ž | ž | ® | ¾ | Î | Þ | î | þ
F |  |  | / | ? | O | _ | o |  |  | Ÿ | ¯ | ¿ | Ï | ß | ï | ÿ


Wingdings フォント キャラクタ コード表

 | 00 | 10 | 20 | 30 | 40 | 50 | 60 | 70 | 80 | 90 | A0 | B0 | C0 | D0 | E0 | F0
0 |  |  |  | 0 | @ | P | ` | p | € |  |  | ° | À | Ð | à | ð
1 |  |  | ! | 1 | A | Q | a | q |  | ‘ | ¡ | ± | Á | Ñ | á | ñ
2 |  |  | " | 2 | B | R | b | r | ‚ | ’ | ¢ | ² | Â | Ò | â | ò
3 |  |  | # | 3 | C | S | c | s | ƒ | “ | £ | ³ | Ã | Ó | ã | ó
4 |  |  | $ | 4 | D | T | d | t | „ | ” | ¤ | ´ | Ä | Ô | ä | ô
5 |  |  | % | 5 | E | U | e | u | … | • | ¥ | µ | Å | Õ | å | õ
6 |  |  | & | 6 | F | V | f | v | † | – | ¦ | ¶ | Æ | Ö | æ | ö
7 |  |  | ' | 7 | G | W | g | w | ‡ | — | § | · | Ç | × | ç | ÷
8 |  |  | ( | 8 | H | X | h | x | ˆ | ˜ | ¨ | ¸ | È | Ø | è | ø
9 |  |  | ) | 9 | I | Y | i | y | ‰ | ™ | © | ¹ | É | Ù | é | ù
A |  |  | * | : | J | Z | j | z | Š | š | ª | º | Ê | Ú | ê | ú
B |  |  | + | ; | K | [ | k | { | ‹ | › | « | » | Ë | Û | ë | û
C |  |  | , | < | L | \ | l | | | Œ | œ | ¬ | ¼ | Ì | Ü | ì | ü
D |  |  | - | = | M | ] | m | } |  |  |  | ½ | Í | Ý | í | ý
E |  |  | . | > | N | ^ | n | ~ | Ž | ž | ® | ¾ | Î | Þ | î | þ
F |  |  | / | ? | O | _ | o |  |  | Ÿ | ¯ | ¿ | Ï | ß | ï | ÿ


Webdings フォント キャラクタ コード表

 | 00 | 10 | 20 | 30 | 40 | 50 | 60 | 70 | 80 | 90 | A0 | B0 | C0 | D0 | E0 | F0
0 |  |  |  | 0 | @ | P | ` | p | € |  |  | ° | À | Ð | à | ð
1 |  |  | ! | 1 | A | Q | a | q |  | ‘ | ¡ | ± | Á | Ñ | á | ñ
2 |  |  | " | 2 | B | R | b | r | ‚ | ’ | ¢ | ² | Â | Ò | â | ò
3 |  |  | # | 3 | C | S | c | s | ƒ | “ | £ | ³ | Ã | Ó | ã | ó
4 |  |  | $ | 4 | D | T | d | t | „ | ” | ¤ | ´ | Ä | Ô | ä | ô
5 |  |  | % | 5 | E | U | e | u | … | • | ¥ | µ | Å | Õ | å | õ
6 |  |  | & | 6 | F | V | f | v | † | – | ¦ | ¶ | Æ | Ö | æ | ö
7 |  |  | ' | 7 | G | W | g | w | ‡ | — | § | · | Ç | × | ç | ÷
8 |  |  | ( | 8 | H | X | h | x | ˆ | ˜ | ¨ | ¸ | È | Ø | è | ø
9 |  |  | ) | 9 | I | Y | i | y | ‰ | ™ | © | ¹ | É | Ù | é | ù
A |  |  | * | : | J | Z | j | z | Š | š | ª | º | Ê | Ú | ê | ú
B |  |  | + | ; | K | [ | k | { | ‹ | › | « | » | Ë | Û | ë | û
C |  |  | , | < | L | \ | l | | | Œ | œ | ¬ | ¼ | Ì | Ü | ì | ü
D |  |  | - | = | M | ] | m | } |  |  |  | ½ | Í | Ý | í | ý
E |  |  | . | > | N | ^ | n | ~ | Ž | ž | ® | ¾ | Î | Þ | î | þ
F |  |  | / | ? | O | _ | o |  |  | Ÿ | ¯ | ¿ | Ï | ß | ï | ÿ


色見本

000000 | 000011 | 000022 | 000033 | 000044 | 000055 | 000066 | 000077 | 000088 | 000099 | 0000AA | 0000BB | 0000CC | 0000DD | 0000EE | 0000FF
001100 | 001111 | 001122 | 001133 | 001144 | 001155 | 001166 | 001177 | 001188 | 001199 | 0011AA | 0011BB | 0011CC | 0011DD | 0011EE | 0011FF
002200 | 002211 | 002222 | 002233 | 002244 | 002255 | 002266 | 002277 | 002288 | 002299 | 0022AA | 0022BB | 0022CC | 0022DD | 0022EE | 0022FF
003300 | 003311 | 003322 | 003333 | 003344 | 003355 | 003366 | 003377 | 003388 | 003399 | 0033AA | 0033BB | 0033CC | 0033DD | 0033EE | 0033FF
004400 | 004411 | 004422 | 004433 | 004444 | 004455 | 004466 | 004477 | 004488 | 004499 | 0044AA | 0044BB | 0044CC | 0044DD | 0044EE | 0044FF
005500 | 005511 | 005522 | 005533 | 005544 | 005555 | 005566 | 005577 | 005588 | 005599 | 0055AA | 0055BB | 0055CC | 0055DD | 0055EE | 0055FF
006600 | 006611 | 006622 | 006633 | 006644 | 006655 | 006666 | 006677 | 006688 | 006699 | 0066AA | 0066BB | 0066CC | 0066DD | 0066EE | 0066FF
007700 | 007711 | 007722 | 007733 | 007744 | 007755 | 007766 | 007777 | 007788 | 007799 | 0077AA | 0077BB | 0077CC | 0077DD | 0077EE | 0077FF
008800 | 008811 | 008822 | 008833 | 008844 | 008855 | 008866 | 008877 | 008888 | 008899 | 0088AA | 0088BB | 0088CC | 0088DD | 0088EE | 0088FF
009900 | 009911 | 009922 | 009933 | 009944 | 009955 | 009966 | 009977 | 009988 | 009999 | 0099AA | 0099BB | 0099CC | 0099DD | 0099EE | 0099FF
00AA00 | 00AA11 | 00AA22 | 00AA33 | 00AA44 | 00AA55 | 00AA66 | 00AA77 | 00AA88 | 00AA99 | 00AAAA | 00AABB | 00AACC | 00AADD | 00AAEE | 00AAFF
00BB00 | 00BB11 | 00BB22 | 00BB33 | 00BB44 | 00BB55 | 00BB66 | 00BB77 | 00BB88 | 00BB99 | 00BBAA | 00BBBB | 00BBCC | 00BBDD | 00BBEE | 00BBFF
00CC00 | 00CC11 | 00CC22 | 00CC33 | 00CC44 | 00CC55 | 00CC66 | 00CC77 | 00CC88 | 00CC99 | 00CCAA | 00CCBB | 00CCCC | 00CCDD | 00CCEE | 00CCFF
00DD00 | 00DD11 | 00DD22 | 00DD33 | 00DD44 | 00DD55 | 00DD66 | 00DD77 | 00DD88 | 00DD99 | 00DDAA | 00DDBB | 00DDCC | 00DDDD | 00DDEE | 00DDFF
00EE00 | 00EE11 | 00EE22 | 00EE33 | 00EE44 | 00EE55 | 00EE66 | 00EE77 | 00EE88 | 00EE99 | 00EEAA | 00EEBB | 00EECC | 00EEDD | 00EEEE | 00EEFF
00FF00 | 00FF11 | 00FF22 | 00FF33 | 00FF44 | 00FF55 | 00FF66 | 00FF77 | 00FF88 | 00FF99 | 00FFAA | 00FFBB | 00FFCC | 00FFDD | 00FFEE | 00FFFF

110000 | 110011 | 110022 | 110033 | 110044 | 110055 | 110066 | 110077 | 110088 | 110099 | 1100AA | 1100BB | 1100CC | 1100DD | 1100EE | 1100FF
111100 | 111111 | 111122 | 111133 | 111144 | 111155 | 111166 | 111177 | 111188 | 111199 | 1111AA | 1111BB | 1111CC | 1111DD | 1111EE | 1111FF
112200 | 112211 | 112222 | 112233 | 112244 | 112255 | 112266 | 112277 | 112288 | 112299 | 1122AA | 1122BB | 1122CC | 1122DD | 1122EE | 1122FF
113300 | 113311 | 113322 | 113333 | 113344 | 113355 | 113366 | 113377 | 113388 | 113399 | 1133AA | 1133BB | 1133CC | 1133DD | 1133EE | 1133FF
114400 | 114411 | 114422 | 114433 | 114444 | 114455 | 114466 | 114477 | 114488 | 114499 | 1144AA | 1144BB | 1144CC | 1144DD | 1144EE | 1144FF
115500 | 115511 | 115522 | 115533 | 115544 | 115555 | 115566 | 115577 | 115588 | 115599 | 1155AA | 1155BB | 1155CC | 1155DD | 1155EE | 1155FF
116600 | 116611 | 116622 | 116633 | 116644 | 116655 | 116666 | 116677 | 116688 | 116699 | 1166AA | 1166BB | 1166CC | 1166DD | 1166EE | 1166FF
117700 | 117711 | 117722 | 117733 | 117744 | 117755 | 117766 | 117777 | 117788 | 117799 | 1177AA | 1177BB | 1177CC | 1177DD | 1177EE | 1177FF
118800 | 118811 | 118822 | 118833 | 118844 | 118855 | 118866 | 118877 | 118888 | 118899 | 1188AA | 1188BB | 1188CC | 1188DD | 1188EE | 1188FF
119900 | 119911 | 119922 | 119933 | 119944 | 119955 | 119966 | 119977 | 119988 | 119999 | 1199AA | 1199BB | 1199CC | 1199DD | 1199EE | 1199FF
11AA00 | 11AA11 | 11AA22 | 11AA33 | 11AA44 | 11AA55 | 11AA66 | 11AA77 | 11AA88 | 11AA99 | 11AAAA | 11AABB | 11AACC | 11AADD | 11AAEE | 11AAFF
11BB00 | 11BB11 | 11BB22 | 11BB33 | 11BB44 | 11BB55 | 11BB66 | 11BB77 | 11BB88 | 11BB99 | 11BBAA | 11BBBB | 11BBCC | 11BBDD | 11BBEE | 11BBFF
11CC00 | 11CC11 | 11CC22 | 11CC33 | 11CC44 | 11CC55 | 11CC66 | 11CC77 | 11CC88 | 11CC99 | 11CCAA | 11CCBB | 11CCCC | 11CCDD | 11CCEE | 11CCFF
11DD00 | 11DD11 | 11DD22 | 11DD33 | 11DD44 | 11DD55 | 11DD66 | 11DD77 | 11DD88 | 11DD99 | 11DDAA | 11DDBB | 11DDCC | 11DDDD | 11DDEE | 11DDFF
11EE00 | 11EE11 | 11EE22 | 11EE33 | 11EE44 | 11EE55 | 11EE66 | 11EE77 | 11EE88 | 11EE99 | 11EEAA | 11EEBB | 11EECC | 11EEDD | 11EEEE | 11EEFF
11FF00 | 11FF11 | 11FF22 | 11FF33 | 11FF44 | 11FF55 | 11FF66 | 11FF77 | 11FF88 | 11FF99 | 11FFAA | 11FFBB | 11FFCC | 11FFDD | 11FFEE | 11FFFF

220000 | 220011 | 220022 | 220033 | 220044 | 220055 | 220066 | 220077 | 220088 | 220099 | 2200AA | 2200BB | 2200CC | 2200DD | 2200EE | 2200FF
221100 | 221111 | 221122 | 221133 | 221144 | 221155 | 221166 | 221177 | 221188 | 221199 | 2211AA | 2211BB | 2211CC | 2211DD | 2211EE | 2211FF
222200 | 222211 | 222222 | 222233 | 222244 | 222255 | 222266 | 222277 | 222288 | 222299 | 2222AA | 2222BB | 2222CC | 2222DD | 2222EE | 2222FF
223300 | 223311 | 223322 | 223333 | 223344 | 223355 | 223366 | 223377 | 223388 | 223399 | 2233AA | 2233BB | 2233CC | 2233DD | 2233EE | 2233FF
224400 | 224411 | 224422 | 224433 | 224444 | 224455 | 224466 | 224477 | 224488 | 224499 | 2244AA | 2244BB | 2244CC | 2244DD | 2244EE | 2244FF
225500 | 225511 | 225522 | 225533 | 225544 | 225555 | 225566 | 225577 | 225588 | 225599 | 2255AA | 2255BB | 2255CC | 2255DD | 2255EE | 2255FF
226600 | 226611 | 226622 | 226633 | 226644 | 226655 | 226666 | 226677 | 226688 | 226699 | 2266AA | 2266BB | 2266CC | 2266DD | 2266EE | 2266FF
227700 | 227711 | 227722 | 227733 | 227744 | 227755 | 227766 | 227777 | 227788 | 227799 | 2277AA | 2277BB | 2277CC | 2277DD | 2277EE | 2277FF
228800 | 228811 | 228822 | 228833 | 228844 | 228855 | 228866 | 228877 | 228888 | 228899 | 2288AA | 2288BB | 2288CC | 2288DD | 2288EE | 2288FF
229900 | 229911 | 229922 | 229933 | 229944 | 229955 | 229966 | 229977 | 229988 | 229999 | 2299AA | 2299BB | 2299CC | 2299DD | 2299EE | 2299FF
22AA00 | 22AA11 | 22AA22 | 22AA33 | 22AA44 | 22AA55 | 22AA66 | 22AA77 | 22AA88 | 22AA99 | 22AAAA | 22AABB | 22AACC | 22AADD | 22AAEE | 22AAFF
22BB00 | 22BB11 | 22BB22 | 22BB33 | 22BB44 | 22BB55 | 22BB66 | 22BB77 | 22BB88 | 22BB99 | 22BBAA | 22BBBB | 22BBCC | 22BBDD | 22BBEE | 22BBFF
22CC00 | 22CC11 | 22CC22 | 22CC33 | 22CC44 | 22CC55 | 22CC66 | 22CC77 | 22CC88 | 22CC99 | 22CCAA | 22CCBB | 22CCCC | 22CCDD | 22CCEE | 22CCFF
22DD00 | 22DD11 | 22DD22 | 22DD33 | 22DD44 | 22DD55 | 22DD66 | 22DD77 | 22DD88 | 22DD99 | 22DDAA | 22DDBB | 22DDCC | 22DDDD | 22DDEE | 22DDFF
22EE00 | 22EE11 | 22EE22 | 22EE33 | 22EE44 | 22EE55 | 22EE66 | 22EE77 | 22EE88 | 22EE99 | 22EEAA | 22EEBB | 22EECC | 22EEDD | 22EEEE | 22EEFF
22FF00 | 22FF11 | 22FF22 | 22FF33 | 22FF44 | 22FF55 | 22FF66 | 22FF77 | 22FF88 | 22FF99 | 22FFAA | 22FFBB | 22FFCC | 22FFDD | 22FFEE | 22FFFF

330000 | 330011 | 330022 | 330033 | 330044 | 330055 | 330066 | 330077 | 330088 | 330099 | 3300AA | 3300BB | 3300CC | 3300DD | 3300EE | 3300FF
331100 | 331111 | 331122 | 331133 | 331144 | 331155 | 331166 | 331177 | 331188 | 331199 | 3311AA | 3311BB | 3311CC | 3311DD | 3311EE | 3311FF
332200 | 332211 | 332222 | 332233 | 332244 | 332255 | 332266 | 332277 | 332288 | 332299 | 3322AA | 3322BB | 3322CC | 3322DD | 3322EE | 3322FF
333300 | 333311 | 333322 | 333333 | 333344 | 333355 | 333366 | 333377 | 333388 | 333399 | 3333AA | 3333BB | 3333CC | 3333DD | 3333EE | 3333FF
334400 | 334411 | 334422 | 334433 | 334444 | 334455 | 334466 | 334477 | 334488 | 334499 | 3344AA | 3344BB | 3344CC | 3344DD | 3344EE | 3344FF
335500 | 335511 | 335522 | 335533 | 335544 | 335555 | 335566 | 335577 | 335588 | 335599 | 3355AA | 3355BB | 3355CC | 3355DD | 3355EE | 3355FF
336600 | 336611 | 336622 | 336633 | 336644 | 336655 | 336666 | 336677 | 336688 | 336699 | 3366AA | 3366BB | 3366CC | 3366DD | 3366EE | 3366FF
337700 | 337711 | 337722 | 337733 | 337744 | 337755 | 337766 | 337777 | 337788 | 337799 | 3377AA | 3377BB | 3377CC | 3377DD | 3377EE | 3377FF
338800 | 338811 | 338822 | 338833 | 338844 | 338855 | 338866 | 338877 | 338888 | 338899 | 3388AA | 3388BB | 3388CC | 3388DD | 3388EE | 3388FF
339900 | 339911 | 339922 | 339933 | 339944 | 339955 | 339966 | 339977 | 339988 | 339999 | 3399AA | 3399BB | 3399CC | 3399DD | 3399EE | 3399FF
33AA00 | 33AA11 | 33AA22 | 33AA33 | 33AA44 | 33AA55 | 33AA66 | 33AA77 | 33AA88 | 33AA99 | 33AAAA | 33AABB | 33AACC | 33AADD | 33AAEE | 33AAFF
33BB00 | 33BB11 | 33BB22 | 33BB33 | 33BB44 | 33BB55 | 33BB66 | 33BB77 | 33BB88 | 33BB99 | 33BBAA | 33BBBB | 33BBCC | 33BBDD | 33BBEE | 33BBFF
33CC00 | 33CC11 | 33CC22 | 33CC33 | 33CC44 | 33CC55 | 33CC66 | 33CC77 | 33CC88 | 33CC99 | 33CCAA | 33CCBB | 33CCCC | 33CCDD | 33CCEE | 33CCFF
33DD00 | 33DD11 | 33DD22 | 33DD33 | 33DD44 | 33DD55 | 33DD66 | 33DD77 | 33DD88 | 33DD99 | 33DDAA | 33DDBB | 33DDCC | 33DDDD | 33DDEE | 33DDFF
33EE00 | 33EE11 | 33EE22 | 33EE33 | 33EE44 | 33EE55 | 33EE66 | 33EE77 | 33EE88 | 33EE99 | 33EEAA | 33EEBB | 33EECC | 33EEDD | 33EEEE | 33EEFF
33FF00 | 33FF11 | 33FF22 | 33FF33 | 33FF44 | 33FF55 | 33FF66 | 33FF77 | 33FF88 | 33FF99 | 33FFAA | 33FFBB | 33FFCC | 33FFDD | 33FFEE | 33FFFF

440000 | 440011 | 440022 | 440033 | 440044 | 440055 | 440066 | 440077 | 440088 | 440099 | 4400AA | 4400BB | 4400CC | 4400DD | 4400EE | 4400FF
441100 | 441111 | 441122 | 441133 | 441144 | 441155 | 441166 | 441177 | 441188 | 441199 | 4411AA | 4411BB | 4411CC | 4411DD | 4411EE | 4411FF
442200 | 442211 | 442222 | 442233 | 442244 | 442255 | 442266 | 442277 | 442288 | 442299 | 4422AA | 4422BB | 4422CC | 4422DD | 4422EE | 4422FF
443300 | 443311 | 443322 | 443333 | 443344 | 443355 | 443366 | 443377 | 443388 | 443399 | 4433AA | 4433BB | 4433CC | 4433DD | 4433EE | 4433FF
444400 | 444411 | 444422 | 444433 | 444444 | 444455 | 444466 | 444477 | 444488 | 444499 | 4444AA | 4444BB | 4444CC | 4444DD | 4444EE | 4444FF
445500 | 445511 | 445522 | 445533 | 445544 | 445555 | 445566 | 445577 | 445588 | 445599 | 4455AA | 4455BB | 4455CC | 4455DD | 4455EE | 4455FF
446600 | 446611 | 446622 | 446633 | 446644 | 446655 | 446666 | 446677 | 446688 | 446699 | 4466AA | 4466BB | 4466CC | 4466DD | 4466EE | 4466FF
447700 | 447711 | 447722 | 447733 | 447744 | 447755 | 447766 | 447777 | 447788 | 447799 | 4477AA | 4477BB | 4477CC | 4477DD | 4477EE | 4477FF
448800 | 448811 | 448822 | 448833 | 448844 | 448855 | 448866 | 448877 | 448888 | 448899 | 4488AA | 4488BB | 4488CC | 4488DD | 4488EE | 4488FF
449900 | 449911 | 449922 | 449933 | 449944 | 449955 | 449966 | 449977 | 449988 | 449999 | 4499AA | 4499BB | 4499CC | 4499DD | 4499EE | 4499FF
44AA00 | 44AA11 | 44AA22 | 44AA33 | 44AA44 | 44AA55 | 44AA66 | 44AA77 | 44AA88 | 44AA99 | 44AAAA | 44AABB | 44AACC | 44AADD | 44AAEE | 44AAFF
44BB00 | 44BB11 | 44BB22 | 44BB33 | 44BB44 | 44BB55 | 44BB66 | 44BB77 | 44BB88 | 44BB99 | 44BBAA | 44BBBB | 44BBCC | 44BBDD | 44BBEE | 44BBFF
44CC00 | 44CC11 | 44CC22 | 44CC33 | 44CC44 | 44CC55 | 44CC66 | 44CC77 | 44CC88 | 44CC99 | 44CCAA | 44CCBB | 44CCCC | 44CCDD | 44CCEE | 44CCFF
44DD00 | 44DD11 | 44DD22 | 44DD33 | 44DD44 | 44DD55 | 44DD66 | 44DD77 | 44DD88 | 44DD99 | 44DDAA | 44DDBB | 44DDCC | 44DDDD | 44DDEE | 44DDFF
44EE00 | 44EE11 | 44EE22 | 44EE33 | 44EE44 | 44EE55 | 44EE66 | 44EE77 | 44EE88 | 44EE99 | 44EEAA | 44EEBB | 44EECC | 44EEDD | 44EEEE | 44EEFF
44FF00 | 44FF11 | 44FF22 | 44FF33 | 44FF44 | 44FF55 | 44FF66 | 44FF77 | 44FF88 | 44FF99 | 44FFAA | 44FFBB | 44FFCC | 44FFDD | 44FFEE | 44FFFF

550000 | 550011 | 550022 | 550033 | 550044 | 550055 | 550066 | 550077 | 550088 | 550099 | 5500AA | 5500BB | 5500CC | 5500DD | 5500EE | 5500FF
551100 | 551111 | 551122 | 551133 | 551144 | 551155 | 551166 | 551177 | 551188 | 551199 | 5511AA | 5511BB | 5511CC | 5511DD | 5511EE | 5511FF
552200 | 552211 | 552222 | 552233 | 552244 | 552255 | 552266 | 552277 | 552288 | 552299 | 5522AA | 5522BB | 5522CC | 5522DD | 5522EE | 5522FF
553300 | 553311 | 553322 | 553333 | 553344 | 553355 | 553366 | 553377 | 553388 | 553399 | 5533AA | 5533BB | 5533CC | 5533DD | 5533EE | 5533FF
554400 | 554411 | 554422 | 554433 | 554444 | 554455 | 554466 | 554477 | 554488 | 554499 | 5544AA | 5544BB | 5544CC | 5544DD | 5544EE | 5544FF
555500 | 555511 | 555522 | 555533 | 555544 | 555555 | 555566 | 555577 | 555588 | 555599 | 5555AA | 5555BB | 5555CC | 5555DD | 5555EE | 5555FF
556600 | 556611 | 556622 | 556633 | 556644 | 556655 | 556666 | 556677 | 556688 | 556699 | 5566AA | 5566BB | 5566CC | 5566DD | 5566EE | 5566FF
557700 | 557711 | 557722 | 557733 | 557744 | 557755 | 557766 | 557777 | 557788 | 557799 | 5577AA | 5577BB | 5577CC | 5577DD | 5577EE | 5577FF
558800 | 558811 | 558822 | 558833 | 558844 | 558855 | 558866 | 558877 | 558888 | 558899 | 5588AA | 5588BB | 5588CC | 5588DD | 5588EE | 5588FF
559900 | 559911 | 559922 | 559933 | 559944 | 559955 | 559966 | 559977 | 559988 | 559999 | 5599AA | 5599BB | 5599CC | 5599DD | 5599EE | 5599FF
55AA00 | 55AA11 | 55AA22 | 55AA33 | 55AA44 | 55AA55 | 55AA66 | 55AA77 | 55AA88 | 55AA99 | 55AAAA | 55AABB | 55AACC | 55AADD | 55AAEE | 55AAFF
55BB00 | 55BB11 | 55BB22 | 55BB33 | 55BB44 | 55BB55 | 55BB66 | 55BB77 | 55BB88 | 55BB99 | 55BBAA | 55BBBB | 55BBCC | 55BBDD | 55BBEE | 55BBFF
55CC00 | 55CC11 | 55CC22 | 55CC33 | 55CC44 | 55CC55 | 55CC66 | 55CC77 | 55CC88 | 55CC99 | 55CCAA | 55CCBB | 55CCCC | 55CCDD | 55CCEE | 55CCFF
55DD00 | 55DD11 | 55DD22 | 55DD33 | 55DD44 | 55DD55 | 55DD66 | 55DD77 | 55DD88 | 55DD99 | 55DDAA | 55DDBB | 55DDCC | 55DDDD | 55DDEE | 55DDFF
55EE00 | 55EE11 | 55EE22 | 55EE33 | 55EE44 | 55EE55 | 55EE66 | 55EE77 | 55EE88 | 55EE99 | 55EEAA | 55EEBB | 55EECC | 55EEDD | 55EEEE | 55EEFF
55FF00 | 55FF11 | 55FF22 | 55FF33 | 55FF44 | 55FF55 | 55FF66 | 55FF77 | 55FF88 | 55FF99 | 55FFAA | 55FFBB | 55FFCC | 55FFDD | 55FFEE | 55FFFF

660000 | 660011 | 660022 | 660033 | 660044 | 660055 | 660066 | 660077 | 660088 | 660099 | 6600AA | 6600BB | 6600CC | 6600DD | 6600EE | 6600FF
661100 | 661111 | 661122 | 661133 | 661144 | 661155 | 661166 | 661177 | 661188 | 661199 | 6611AA | 6611BB | 6611CC | 6611DD | 6611EE | 6611FF
662200 | 662211 | 662222 | 662233 | 662244 | 662255 | 662266 | 662277 | 662288 | 662299 | 6622AA | 6622BB | 6622CC | 6622DD | 6622EE | 6622FF
663300 | 663311 | 663322 | 663333 | 663344 | 663355 | 663366 | 663377 | 663388 | 663399 | 6633AA | 6633BB | 6633CC | 6633DD | 6633EE | 6633FF
664400 | 664411 | 664422 | 664433 | 664444 | 664455 | 664466 | 664477 | 664488 | 664499 | 6644AA | 6644BB | 6644CC | 6644DD | 6644EE | 6644FF
665500 | 665511 | 665522 | 665533 | 665544 | 665555 | 665566 | 665577 | 665588 | 665599 | 6655AA | 6655BB | 6655CC | 6655DD | 6655EE | 6655FF
666600 | 666611 | 666622 | 666633 | 666644 | 666655 | 666666 | 666677 | 666688 | 666699 | 6666AA | 6666BB | 6666CC | 6666DD | 6666EE | 6666FF
667700 | 667711 | 667722 | 667733 | 667744 | 667755 | 667766 | 667777 | 667788 | 667799 | 6677AA | 6677BB | 6677CC | 6677DD | 6677EE | 6677FF
668800 | 668811 | 668822 | 668833 | 668844 | 668855 | 668866 | 668877 | 668888 | 668899 | 6688AA | 6688BB | 6688CC | 6688DD | 6688EE | 6688FF
669900 | 669911 | 669922 | 669933 | 669944 | 669955 | 669966 | 669977 | 669988 | 669999 | 6699AA | 6699BB | 6699CC | 6699DD | 6699EE | 6699FF
66AA00 | 66AA11 | 66AA22 | 66AA33 | 66AA44 | 66AA55 | 66AA66 | 66AA77 | 66AA88 | 66AA99 | 66AAAA | 66AABB | 66AACC | 66AADD | 66AAEE | 66AAFF
66BB00 | 66BB11 | 66BB22 | 66BB33 | 66BB44 | 66BB55 | 66BB66 | 66BB77 | 66BB88 | 66BB99 | 66BBAA | 66BBBB | 66BBCC | 66BBDD | 66BBEE | 66BBFF
66CC00 | 66CC11 | 66CC22 | 66CC33 | 66CC44 | 66CC55 | 66CC66 | 66CC77 | 66CC88 | 66CC99 | 66CCAA | 66CCBB | 66CCCC | 66CCDD | 66CCEE | 66CCFF
66DD00 | 66DD11 | 66DD22 | 66DD33 | 66DD44 | 66DD55 | 66DD66 | 66DD77 | 66DD88 | 66DD99 | 66DDAA | 66DDBB | 66DDCC | 66DDDD | 66DDEE | 66DDFF
66EE00 | 66EE11 | 66EE22 | 66EE33 | 66EE44 | 66EE55 | 66EE66 | 66EE77 | 66EE88 | 66EE99 | 66EEAA | 66EEBB | 66EECC | 66EEDD | 66EEEE | 66EEFF
66FF00 | 66FF11 | 66FF22 | 66FF33 | 66FF44 | 66FF55 | 66FF66 | 66FF77 | 66FF88 | 66FF99 | 66FFAA | 66FFBB | 66FFCC | 66FFDD | 66FFEE | 66FFFF

770000 | 770011 | 770022 | 770033 | 770044 | 770055 | 770066 | 770077 | 770088 | 770099 | 7700AA | 7700BB | 7700CC | 7700DD | 7700EE | 7700FF
771100 | 771111 | 771122 | 771133 | 771144 | 771155 | 771166 | 771177 | 771188 | 771199 | 7711AA | 7711BB | 7711CC | 7711DD | 7711EE | 7711FF
772200 | 772211 | 772222 | 772233 | 772244 | 772255 | 772266 | 772277 | 772288 | 772299 | 7722AA | 7722BB | 7722CC | 7722DD | 7722EE | 7722FF
773300 | 773311 | 773322 | 773333 | 773344 | 773355 | 773366 | 773377 | 773388 | 773399 | 7733AA | 7733BB | 7733CC | 7733DD | 7733EE | 7733FF
774400 | 774411 | 774422 | 774433 | 774444 | 774455 | 774466 | 774477 | 774488 | 774499 | 7744AA | 7744BB | 7744CC | 7744DD | 7744EE | 7744FF
775500 | 775511 | 775522 | 775533 | 775544 | 775555 | 775566 | 775577 | 775588 | 775599 | 7755AA | 7755BB | 7755CC | 7755DD | 7755EE | 7755FF
776600 | 776611 | 776622 | 776633 | 776644 | 776655 | 776666 | 776677 | 776688 | 776699 | 7766AA | 7766BB | 7766CC | 7766DD | 7766EE | 7766FF
777700 | 777711 | 777722 | 777733 | 777744 | 777755 | 777766 | 777777 | 777788 | 777799 | 7777AA | 7777BB | 7777CC | 7777DD | 7777EE | 7777FF
778800 | 778811 | 778822 | 778833 | 778844 | 778855 | 778866 | 778877 | 778888 | 778899 | 7788AA | 7788BB | 7788CC | 7788DD | 7788EE | 7788FF
779900 | 779911 | 779922 | 779933 | 779944 | 779955 | 779966 | 779977 | 779988 | 779999 | 7799AA | 7799BB | 7799CC | 7799DD | 7799EE | 7799FF
77AA00 | 77AA11 | 77AA22 | 77AA33 | 77AA44 | 77AA55 | 77AA66 | 77AA77 | 77AA88 | 77AA99 | 77AAAA | 77AABB | 77AACC | 77AADD | 77AAEE | 77AAFF
77BB00 | 77BB11 | 77BB22 | 77BB33 | 77BB44 | 77BB55 | 77BB66 | 77BB77 | 77BB88 | 77BB99 | 77BBAA | 77BBBB | 77BBCC | 77BBDD | 77BBEE | 77BBFF
77CC00 | 77CC11 | 77CC22 | 77CC33 | 77CC44 | 77CC55 | 77CC66 | 77CC77 | 77CC88 | 77CC99 | 77CCAA | 77CCBB | 77CCCC | 77CCDD | 77CCEE | 77CCFF
77DD00 | 77DD11 | 77DD22 | 77DD33 | 77DD44 | 77DD55 | 77DD66 | 77DD77 | 77DD88 | 77DD99 | 77DDAA | 77DDBB | 77DDCC | 77DDDD | 77DDEE | 77DDFF
77EE00 | 77EE11 | 77EE22 | 77EE33 | 77EE44 | 77EE55 | 77EE66 | 77EE77 | 77EE88 | 77EE99 | 77EEAA | 77EEBB | 77EECC | 77EEDD | 77EEEE | 77EEFF
77FF00 | 77FF11 | 77FF22 | 77FF33 | 77FF44 | 77FF55 | 77FF66 | 77FF77 | 77FF88 | 77FF99 | 77FFAA | 77FFBB | 77FFCC | 77FFDD | 77FFEE | 77FFFF

880000 | 880011 | 880022 | 880033 | 880044 | 880055 | 880066 | 880077 | 880088 | 880099 | 8800AA | 8800BB | 8800CC | 8800DD | 8800EE | 8800FF
881100 | 881111 | 881122 | 881133 | 881144 | 881155 | 881166 | 881177 | 881188 | 881199 | 8811AA | 8811BB | 8811CC | 8811DD | 8811EE | 8811FF
882200 | 882211 | 882222 | 882233 | 882244 | 882255 | 882266 | 882277 | 882288 | 882299 | 8822AA | 8822BB | 8822CC | 8822DD | 8822EE | 8822FF
883300 | 883311 | 883322 | 883333 | 883344 | 883355 | 883366 | 883377 | 883388 | 883399 | 8833AA | 8833BB | 8833CC | 8833DD | 8833EE | 8833FF
884400 | 884411 | 884422 | 884433 | 884444 | 884455 | 884466 | 884477 | 884488 | 884499 | 8844AA | 8844BB | 8844CC | 8844DD | 8844EE | 8844FF
885500 | 885511 | 885522 | 885533 | 885544 | 885555 | 885566 | 885577 | 885588 | 885599 | 8855AA | 8855BB | 8855CC | 8855DD | 8855EE | 8855FF
886600 | 886611 | 886622 | 886633 | 886644 | 886655 | 886666 | 886677 | 886688 | 886699 | 8866AA | 8866BB | 8866CC | 8866DD | 8866EE | 8866FF
887700 | 887711 | 887722 | 887733 | 887744 | 887755 | 887766 | 887777 | 887788 | 887799 | 8877AA | 8877BB | 8877CC | 8877DD | 8877EE | 8877FF
888800 | 888811 | 888822 | 888833 | 888844 | 888855 | 888866 | 888877 | 888888 | 888899 | 8888AA | 8888BB | 8888CC | 8888DD | 8888EE | 8888FF
889900 | 889911 | 889922 | 889933 | 889944 | 889955 | 889966 | 889977 | 889988 | 889999 | 8899AA | 8899BB | 8899CC | 8899DD | 8899EE | 8899FF
88AA00 | 88AA11 | 88AA22 | 88AA33 | 88AA44 | 88AA55 | 88AA66 | 88AA77 | 88AA88 | 88AA99 | 88AAAA | 88AABB | 88AACC | 88AADD | 88AAEE | 88AAFF
88BB00 | 88BB11 | 88BB22 | 88BB33 | 88BB44 | 88BB55 | 88BB66 | 88BB77 | 88BB88 | 88BB99 | 88BBAA | 88BBBB | 88BBCC | 88BBDD | 88BBEE | 88BBFF
88CC00 | 88CC11 | 88CC22 | 88CC33 | 88CC44 | 88CC55 | 88CC66 | 88CC77 | 88CC88 | 88CC99 | 88CCAA | 88CCBB | 88CCCC | 88CCDD | 88CCEE | 88CCFF
88DD00 | 88DD11 | 88DD22 | 88DD33 | 88DD44 | 88DD55 | 88DD66 | 88DD77 | 88DD88 | 88DD99 | 88DDAA | 88DDBB | 88DDCC | 88DDDD | 88DDEE | 88DDFF
88EE00 | 88EE11 | 88EE22 | 88EE33 | 88EE44 | 88EE55 | 88EE66 | 88EE77 | 88EE88 | 88EE99 | 88EEAA | 88EEBB | 88EECC | 88EEDD | 88EEEE | 88EEFF
88FF00 | 88FF11 | 88FF22 | 88FF33 | 88FF44 | 88FF55 | 88FF66 | 88FF77 | 88FF88 | 88FF99 | 88FFAA | 88FFBB | 88FFCC | 88FFDD | 88FFEE | 88FFFF

990000 | 990011 | 990022 | 990033 | 990044 | 990055 | 990066 | 990077 | 990088 | 990099 | 9900AA | 9900BB | 9900CC | 9900DD | 9900EE | 9900FF
991100 | 991111 | 991122 | 991133 | 991144 | 991155 | 991166 | 991177 | 991188 | 991199 | 9911AA | 9911BB | 9911CC | 9911DD | 9911EE | 9911FF
992200 | 992211 | 992222 | 992233 | 992244 | 992255 | 992266 | 992277 | 992288 | 992299 | 9922AA | 9922BB | 9922CC | 9922DD | 9922EE | 9922FF
993300 | 993311 | 993322 | 993333 | 993344 | 993355 | 993366 | 993377 | 993388 | 993399 | 9933AA | 9933BB | 9933CC | 9933DD | 9933EE | 9933FF
994400 | 994411 | 994422 | 994433 | 994444 | 994455 | 994466 | 994477 | 994488 | 994499 | 9944AA | 9944BB | 9944CC | 9944DD | 9944EE | 9944FF
995500 | 995511 | 995522 | 995533 | 995544 | 995555 | 995566 | 995577 | 995588 | 995599 | 9955AA | 9955BB | 9955CC | 9955DD | 9955EE | 9955FF
996600 | 996611 | 996622 | 996633 | 996644 | 996655 | 996666 | 996677 | 996688 | 996699 | 9966AA | 9966BB | 9966CC | 9966DD | 9966EE | 9966FF
997700 | 997711 | 997722 | 997733 | 997744 | 997755 | 997766 | 997777 | 997788 | 997799 | 9977AA | 9977BB | 9977CC | 9977DD | 9977EE | 9977FF
998800 | 998811 | 998822 | 998833 | 998844 | 998855 | 998866 | 998877 | 998888 | 998899 | 9988AA | 9988BB | 9988CC | 9988DD | 9988EE | 9988FF
999900 | 999911 | 999922 | 999933 | 999944 | 999955 | 999966 | 999977 | 999988 | 999999 | 9999AA | 9999BB | 9999CC | 9999DD | 9999EE | 9999FF
99AA00 | 99AA11 | 99AA22 | 99AA33 | 99AA44 | 99AA55 | 99AA66 | 99AA77 | 99AA88 | 99AA99 | 99AAAA | 99AABB | 99AACC | 99AADD | 99AAEE | 99AAFF
99BB00 | 99BB11 | 99BB22 | 99BB33 | 99BB44 | 99BB55 | 99BB66 | 99BB77 | 99BB88 | 99BB99 | 99BBAA | 99BBBB | 99BBCC | 99BBDD | 99BBEE | 99BBFF
99CC00 | 99CC11 | 99CC22 | 99CC33 | 99CC44 | 99CC55 | 99CC66 | 99CC77 | 99CC88 | 99CC99 | 99CCAA | 99CCBB | 99CCCC | 99CCDD | 99CCEE | 99CCFF
99DD00 | 99DD11 | 99DD22 | 99DD33 | 99DD44 | 99DD55 | 99DD66 | 99DD77 | 99DD88 | 99DD99 | 99DDAA | 99DDBB | 99DDCC | 99DDDD | 99DDEE | 99DDFF
99EE00 | 99EE11 | 99EE22 | 99EE33 | 99EE44 | 99EE55 | 99EE66 | 99EE77 | 99EE88 | 99EE99 | 99EEAA | 99EEBB | 99EECC | 99EEDD | 99EEEE | 99EEFF
99FF00 | 99FF11 | 99FF22 | 99FF33 | 99FF44 | 99FF55 | 99FF66 | 99FF77 | 99FF88 | 99FF99 | 99FFAA | 99FFBB | 99FFCC | 99FFDD | 99FFEE | 99FFFF

AA0000 | AA0011 | AA0022 | AA0033 | AA0044 | AA0055 | AA0066 | AA0077 | AA0088 | AA0099 | AA00AA | AA00BB | AA00CC | AA00DD | AA00EE | AA00FF
AA1100 | AA1111 | AA1122 | AA1133 | AA1144 | AA1155 | AA1166 | AA1177 | AA1188 | AA1199 | AA11AA | AA11BB | AA11CC | AA11DD | AA11EE | AA11FF
AA2200 | AA2211 | AA2222 | AA2233 | AA2244 | AA2255 | AA2266 | AA2277 | AA2288 | AA2299 | AA22AA | AA22BB | AA22CC | AA22DD | AA22EE | AA22FF
AA3300 | AA3311 | AA3322 | AA3333 | AA3344 | AA3355 | AA3366 | AA3377 | AA3388 | AA3399 | AA33AA | AA33BB | AA33CC | AA33DD | AA33EE | AA33FF
AA4400 | AA4411 | AA4422 | AA4433 | AA4444 | AA4455 | AA4466 | AA4477 | AA4488 | AA4499 | AA44AA | AA44BB | AA44CC | AA44DD | AA44EE | AA44FF
AA5500 | AA5511 | AA5522 | AA5533 | AA5544 | AA5555 | AA5566 | AA5577 | AA5588 | AA5599 | AA55AA | AA55BB | AA55CC | AA55DD | AA55EE | AA55FF
AA6600 | AA6611 | AA6622 | AA6633 | AA6644 | AA6655 | AA6666 | AA6677 | AA6688 | AA6699 | AA66AA | AA66BB | AA66CC | AA66DD | AA66EE | AA66FF
AA7700 | AA7711 | AA7722 | AA7733 | AA7744 | AA7755 | AA7766 | AA7777 | AA7788 | AA7799 | AA77AA | AA77BB | AA77CC | AA77DD | AA77EE | AA77FF
AA8800 | AA8811 | AA8822 | AA8833 | AA8844 | AA8855 | AA8866 | AA8877 | AA8888 | AA8899 | AA88AA | AA88BB | AA88CC | AA88DD | AA88EE | AA88FF
AA9900 | AA9911 | AA9922 | AA9933 | AA9944 | AA9955 | AA9966 | AA9977 | AA9988 | AA9999 | AA99AA | AA99BB | AA99CC | AA99DD | AA99EE | AA99FF
AAAA00 | AAAA11 | AAAA22 | AAAA33 | AAAA44 | AAAA55 | AAAA66 | AAAA77 | AAAA88 | AAAA99 | AAAAAA | AAAABB | AAAACC | AAAADD | AAAAEE | AAAAFF
AABB00 | AABB11 | AABB22 | AABB33 | AABB44 | AABB55 | AABB66 | AABB77 | AABB88 | AABB99 | AABBAA | AABBBB | AABBCC | AABBDD | AABBEE | AABBFF
AACC00 | AACC11 | AACC22 | AACC33 | AACC44 | AACC55 | AACC66 | AACC77 | AACC88 | AACC99 | AACCAA | AACCBB | AACCCC | AACCDD | AACCEE | AACCFF
AADD00 | AADD11 | AADD22 | AADD33 | AADD44 | AADD55 | AADD66 | AADD77 | AADD88 | AADD99 | AADDAA | AADDBB | AADDCC | AADDDD | AADDEE | AADDFF
AAEE00 | AAEE11 | AAEE22 | AAEE33 | AAEE44 | AAEE55 | AAEE66 | AAEE77 | AAEE88 | AAEE99 | AAEEAA | AAEEBB | AAEECC | AAEEDD | AAEEEE | AAEEFF
AAFF00 | AAFF11 | AAFF22 | AAFF33 | AAFF44 | AAFF55 | AAFF66 | AAFF77 | AAFF88 | AAFF99 | AAFFAA | AAFFBB | AAFFCC | AAFFDD | AAFFEE | AAFFFF

BB0000 | BB0011 | BB0022 | BB0033 | BB0044 | BB0055 | BB0066 | BB0077 | BB0088 | BB0099 | BB00AA | BB00BB | BB00CC | BB00DD | BB00EE | BB00FF
BB1100 | BB1111 | BB1122 | BB1133 | BB1144 | BB1155 | BB1166 | BB1177 | BB1188 | BB1199 | BB11AA | BB11BB | BB11CC | BB11DD | BB11EE | BB11FF
BB2200 | BB2211 | BB2222 | BB2233 | BB2244 | BB2255 | BB2266 | BB2277 | BB2288 | BB2299 | BB22AA | BB22BB | BB22CC | BB22DD | BB22EE | BB22FF
BB3300 | BB3311 | BB3322 | BB3333 | BB3344 | BB3355 | BB3366 | BB3377 | BB3388 | BB3399 | BB33AA | BB33BB | BB33CC | BB33DD | BB33EE | BB33FF
BB4400 | BB4411 | BB4422 | BB4433 | BB4444 | BB4455 | BB4466 | BB4477 | BB4488 | BB4499 | BB44AA | BB44BB | BB44CC | BB44DD | BB44EE | BB44FF
BB5500 | BB5511 | BB5522 | BB5533 | BB5544 | BB5555 | BB5566 | BB5577 | BB5588 | BB5599 | BB55AA | BB55BB | BB55CC | BB55DD | BB55EE | BB55FF
BB6600 | BB6611 | BB6622 | BB6633 | BB6644 | BB6655 | BB6666 | BB6677 | BB6688 | BB6699 | BB66AA | BB66BB | BB66CC | BB66DD | BB66EE | BB66FF
BB7700 | BB7711 | BB7722 | BB7733 | BB7744 | BB7755 | BB7766 | BB7777 | BB7788 | BB7799 | BB77AA | BB77BB | BB77CC | BB77DD | BB77EE | BB77FF
BB8800 | BB8811 | BB8822 | BB8833 | BB8844 | BB8855 | BB8866 | BB8877 | BB8888 | BB8899 | BB88AA | BB88BB | BB88CC | BB88DD | BB88EE | BB88FF
BB9900 | BB9911 | BB9922 | BB9933 | BB9944 | BB9955 | BB9966 | BB9977 | BB9988 | BB9999 | BB99AA | BB99BB | BB99CC | BB99DD | BB99EE | BB99FF
BBAA00 | BBAA11 | BBAA22 | BBAA33 | BBAA44 | BBAA55 | BBAA66 | BBAA77 | BBAA88 | BBAA99 | BBAAAA | BBAABB | BBAACC | BBAADD | BBAAEE | BBAAFF
BBBB00 | BBBB11 | BBBB22 | BBBB33 | BBBB44 | BBBB55 | BBBB66 | BBBB77 | BBBB88 | BBBB99 | BBBBAA | BBBBBB | BBBBCC | BBBBDD | BBBBEE | BBBBFF
BBCC00 | BBCC11 | BBCC22 | BBCC33 | BBCC44 | BBCC55 | BBCC66 | BBCC77 | BBCC88 | BBCC99 | BBCCAA | BBCCBB | BBCCCC | BBCCDD | BBCCEE | BBCCFF
BBDD00 | BBDD11 | BBDD22 | BBDD33 | BBDD44 | BBDD55 | BBDD66 | BBDD77 | BBDD88 | BBDD99 | BBDDAA | BBDDBB | BBDDCC | BBDDDD | BBDDEE | BBDDFF
BBEE00 | BBEE11 | BBEE22 | BBEE33 | BBEE44 | BBEE55 | BBEE66 | BBEE77 | BBEE88 | BBEE99 | BBEEAA | BBEEBB | BBEECC | BBEEDD | BBEEEE | BBEEFF
BBFF00 | BBFF11 | BBFF22 | BBFF33 | BBFF44 | BBFF55 | BBFF66 | BBFF77 | BBFF88 | BBFF99 | BBFFAA | BBFFBB | BBFFCC | BBFFDD | BBFFEE | BBFFFF

CC0000 | CC0011 | CC0022 | CC0033 | CC0044 | CC0055 | CC0066 | CC0077 | CC0088 | CC0099 | CC00AA | CC00BB | CC00CC | CC00DD | CC00EE | CC00FF
CC1100 | CC1111 | CC1122 | CC1133 | CC1144 | CC1155 | CC1166 | CC1177 | CC1188 | CC1199 | CC11AA | CC11BB | CC11CC | CC11DD | CC11EE | CC11FF
CC2200 | CC2211 | CC2222 | CC2233 | CC2244 | CC2255 | CC2266 | CC2277 | CC2288 | CC2299 | CC22AA | CC22BB | CC22CC | CC22DD | CC22EE | CC22FF
CC3300 | CC3311 | CC3322 | CC3333 | CC3344 | CC3355 | CC3366 | CC3377 | CC3388 | CC3399 | CC33AA | CC33BB | CC33CC | CC33DD | CC33EE | CC33FF
CC4400 | CC4411 | CC4422 | CC4433 | CC4444 | CC4455 | CC4466 | CC4477 | CC4488 | CC4499 | CC44AA | CC44BB | CC44CC | CC44DD | CC44EE | CC44FF
CC5500 | CC5511 | CC5522 | CC5533 | CC5544 | CC5555 | CC5566 | CC5577 | CC5588 | CC5599 | CC55AA | CC55BB | CC55CC | CC55DD | CC55EE | CC55FF
CC6600 | CC6611 | CC6622 | CC6633 | CC6644 | CC6655 | CC6666 | CC6677 | CC6688 | CC6699 | CC66AA | CC66BB | CC66CC | CC66DD | CC66EE | CC66FF
CC7700 | CC7711 | CC7722 | CC7733 | CC7744 | CC7755 | CC7766 | CC7777 | CC7788 | CC7799 | CC77AA | CC77BB | CC77CC | CC77DD | CC77EE | CC77FF
CC8800 | CC8811 | CC8822 | CC8833 | CC8844 | CC8855 | CC8866 | CC8877 | CC8888 | CC8899 | CC88AA | CC88BB | CC88CC | CC88DD | CC88EE | CC88FF
CC9900 | CC9911 | CC9922 | CC9933 | CC9944 | CC9955 | CC9966 | CC9977 | CC9988 | CC9999 | CC99AA | CC99BB | CC99CC | CC99DD | CC99EE | CC99FF
CCAA00 | CCAA11 | CCAA22 | CCAA33 | CCAA44 | CCAA55 | CCAA66 | CCAA77 | CCAA88 | CCAA99 | CCAAAA | CCAABB | CCAACC | CCAADD | CCAAEE | CCAAFF
CCBB00 | CCBB11 | CCBB22 | CCBB33 | CCBB44 | CCBB55 | CCBB66 | CCBB77 | CCBB88 | CCBB99 | CCBBAA | CCBBBB | CCBBCC | CCBBDD | CCBBEE | CCBBFF
CCCC00 | CCCC11 | CCCC22 | CCCC33 | CCCC44 | CCCC55 | CCCC66 | CCCC77 | CCCC88 | CCCC99 | CCCCAA | CCCCBB | CCCCCC | CCCCDD | CCCCEE | CCCCFF
CCDD00 | CCDD11 | CCDD22 | CCDD33 | CCDD44 | CCDD55 | CCDD66 | CCDD77 | CCDD88 | CCDD99 | CCDDAA | CCDDBB | CCDDCC | CCDDDD | CCDDEE | CCDDFF
CCEE00 | CCEE11 | CCEE22 | CCEE33 | CCEE44 | CCEE55 | CCEE66 | CCEE77 | CCEE88 | CCEE99 | CCEEAA | CCEEBB | CCEECC | CCEEDD | CCEEEE | CCEEFF
CCFF00 | CCFF11 | CCFF22 | CCFF33 | CCFF44 | CCFF55 | CCFF66 | CCFF77 | CCFF88 | CCFF99 | CCFFAA | CCFFBB | CCFFCC | CCFFDD | CCFFEE | CCFFFF

EE0000 | EE0011 | EE0022 | EE0033 | EE0044 | EE0055 | EE0066 | EE0077 | EE0088 | EE0099 | EE00AA | EE00BB | EE00CC | EE00DD | EE00EE | EE00FF
EE1100 | EE1111 | EE1122 | EE1133 | EE1144 | EE1155 | EE1166 | EE1177 | EE1188 | EE1199 | EE11AA | EE11BB | EE11CC | EE11DD | EE11EE | EE11FF
EE2200 | EE2211 | EE2222 | EE2233 | EE2244 | EE2255 | EE2266 | EE2277 | EE2288 | EE2299 | EE22AA | EE22BB | EE22CC | EE22DD | EE22EE | EE22FF
EE3300 | EE3311 | EE3322 | EE3333 | EE3344 | EE3355 | EE3366 | EE3377 | EE3388 | EE3399 | EE33AA | EE33BB | EE33CC | EE33DD | EE33EE | EE33FF
EE4400 | EE4411 | EE4422 | EE4433 | EE4444 | EE4455 | EE4466 | EE4477 | EE4488 | EE4499 | EE44AA | EE44BB | EE44CC | EE44DD | EE44EE | EE44FF
EE5500 | EE5511 | EE5522 | EE5533 | EE5544 | EE5555 | EE5566 | EE5577 | EE5588 | EE5599 | EE55AA | EE55BB | EE55CC | EE55DD | EE55EE | EE55FF
EE6600 | EE6611 | EE6622 | EE6633 | EE6644 | EE6655 | EE6666 | EE6677 | EE6688 | EE6699 | EE66AA | EE66BB | EE66CC | EE66DD | EE66EE | EE66FF
EE7700 | EE7711 | EE7722 | EE7733 | EE7744 | EE7755 | EE7766 | EE7777 | EE7788 | EE7799 | EE77AA | EE77BB | EE77CC | EE77DD | EE77EE | EE77FF
EE8800 | EE8811 | EE8822 | EE8833 | EE8844 | EE8855 | EE8866 | EE8877 | EE8888 | EE8899 | EE88AA | EE88BB | EE88CC | EE88DD | EE88EE | EE88FF
EE9900 | EE9911 | EE9922 | EE9933 | EE9944 | EE9955 | EE9966 | EE9977 | EE9988 | EE9999 | EE99AA | EE99BB | EE99CC | EE99DD | EE99EE | EE99FF
EEAA00 | EEAA11 | EEAA22 | EEAA33 | EEAA44 | EEAA55 | EEAA66 | EEAA77 | EEAA88 | EEAA99 | EEAAAA | EEAABB | EEAACC | EEAADD | EEAAEE | EEAAFF
EEBB00 | EEBB11 | EEBB22 | EEBB33 | EEBB44 | EEBB55 | EEBB66 | EEBB77 | EEBB88 | EEBB99 | EEBBAA | EEBBBB | EEBBCC | EEBBDD | EEBBEE | EEBBFF
EECC00 | EECC11 | EECC22 | EECC33 | EECC44 | EECC55 | EECC66 | EECC77 | EECC88 | EECC99 | EECCAA | EECCBB | EECCCC | EECCDD | EECCEE | EECCFF
EEDD00 | EEDD11 | EEDD22 | EEDD33 | EEDD44 | EEDD55 | EEDD66 | EEDD77 | EEDD88 | EEDD99 | EEDDAA | EEDDBB | EEDDCC | EEDDDD | EEDDEE | EEDDFF
EEEE00 | EEEE11 | EEEE22 | EEEE33 | EEEE44 | EEEE55 | EEEE66 | EEEE77 | EEEE88 | EEEE99 | EEEEAA | EEEEBB | EEEECC | EEEEDD | EEEEEE | EEEEFF
EEFF00 | EEFF11 | EEFF22 | EEFF33 | EEFF44 | EEFF55 | EEFF66 | EEFF77 | EEFF88 | EEFF99 | EEFFAA | EEFFBB | EEFFCC | EEFFDD | EEFFEE | EEFFFF

FF0000 | FF0011 | FF0022 | FF0033 | FF0044 | FF0055 | FF0066 | FF0077 | FF0088 | FF0099 | FF00AA | FF00BB | FF00CC | FF00DD | FF00EE | FF00FF
FF1100 | FF1111 | FF1122 | FF1133 | FF1144 | FF1155 | FF1166 | FF1177 | FF1188 | FF1199 | FF11AA | FF11BB | FF11CC | FF11DD | FF11EE | FF11FF
FF2200 | FF2211 | FF2222 | FF2233 | FF2244 | FF2255 | FF2266 | FF2277 | FF2288 | FF2299 | FF22AA | FF22BB | FF22CC | FF22DD | FF22EE | FF22FF
FF3300 | FF3311 | FF3322 | FF3333 | FF3344 | FF3355 | FF3366 | FF3377 | FF3388 | FF3399 | FF33AA | FF33BB | FF33CC | FF33DD | FF33EE | FF33FF
FF4400 | FF4411 | FF4422 | FF4433 | FF4444 | FF4455 | FF4466 | FF4477 | FF4488 | FF4499 | FF44AA | FF44BB | FF44CC | FF44DD | FF44EE | FF44FF
FF5500 | FF5511 | FF5522 | FF5533 | FF5544 | FF5555 | FF5566 | FF5577 | FF5588 | FF5599 | FF55AA | FF55BB | FF55CC | FF55DD | FF55EE | FF55FF
FF6600 | FF6611 | FF6622 | FF6633 | FF6644 | FF6655 | FF6666 | FF6677 | FF6688 | FF6699 | FF66AA | FF66BB | FF66CC | FF66DD | FF66EE | FF66FF
FF7700 | FF7711 | FF7722 | FF7733 | FF7744 | FF7755 | FF7766 | FF7777 | FF7788 | FF7799 | FF77AA | FF77BB | FF77CC | FF77DD | FF77EE | FF77FF
FF8800 | FF8811 | FF8822 | FF8833 | FF8844 | FF8855 | FF8866 | FF8877 | FF8888 | FF8899 | FF88AA | FF88BB | FF88CC | FF88DD | FF88EE | FF88FF
FF9900 | FF9911 | FF9922 | FF9933 | FF9944 | FF9955 | FF9966 | FF9977 | FF9988 | FF9999 | FF99AA | FF99BB | FF99CC | FF99DD | FF99EE | FF99FF
FFAA00 | FFAA11 | FFAA22 | FFAA33 | FFAA44 | FFAA55 | FFAA66 | FFAA77 | FFAA88 | FFAA99 | FFAAAA | FFAABB | FFAACC | FFAADD | FFAAEE | FFAAFF
FFBB00 | FFBB11 | FFBB22 | FFBB33 | FFBB44 | FFBB55 | FFBB66 | FFBB77 | FFBB88 | FFBB99 | FFBBAA | FFBBBB | FFBBCC | FFBBDD | FFBBEE | FFBBFF
FFCC00 | FFCC11 | FFCC22 | FFCC33 | FFCC44 | FFCC55 | FFCC66 | FFCC77 | FFCC88 | FFCC99 | FFCCAA | FFCCBB | FFCCCC | FFCCDD | FFCCEE | FFCCFF
FFDD00 | FFDD11 | FFDD22 | FFDD33 | FFDD44 | FFDD55 | FFDD66 | FFDD77 | FFDD88 | FFDD99 | FFDDAA | FFDDBB | FFDDCC | FFDDDD | FFDDEE | FFDDFF
FFEE00 | FFEE11 | FFEE22 | FFEE33 | FFEE44 | FFEE55 | FFEE66 | FFEE77 | FFEE88 | FFEE99 | FFEEAA | FFEEBB | FFEECC | FFEEDD | FFEEEE | FFEEFF
FFFF00 | FFFF11 | FFFF22 | FFFF33 | FFFF44 | FFFF55 | FFFF66 | FFFF77 | FFFF88 | FFFF99 | FFFFAA | FFFFBB | FFFFCC | FFFFDD | FFFFEE | FFFFFF

※数値は RGB 値 (赤緑青)


用語集

ISO/JIS/ANSI

ISO、JIS、ANSI はそれぞれ国際標準化機構 (International Organization for Standardization)、日本工業規格 (Japanese Industrial Standard)、米国規格協会 (American National Standard Institute) の略称です。C 言語の文法は、これらの規格によって定められています。

Light C for x86 は ANSI X3.159 (C89：1989 年 12 月) に準拠しています。ISO/IEC 9899:1990 Programming Languages-C (C90：1990 年 12 月)、および日本工業規格の JIS X 3010:1993「プログラミング言語 C」も基本的に ANSI X3.159 と同じです。

参照 ISO/JIS/ANSI 規格との互換性

FILE 構造体

ファイルを管理するための構造体で、stdio.h で定義されています。この構造体自体は ANSI 規格ですが、内部 (メンバ) の詳細はコンパイルによって異なります。通常、FILE のメンバを気にかける必要はありません。

Light Macro Assembler

Microsoft Macro Assembler (MS-MASM) V6.0 と互換性のある MS-DOS 用のマクロ アセンブラです。http://www.tamasoft.co.jp/lasm/ から体験版を入手できます。

wchar_t

16 ビットの文字コードです。「文字リテラル」を参照してください。

アライン (境界整列)

データのアドレス、サイズ、オフセットなどを切りのよい値に揃えることを意味する言葉です。

一般にデータはなるべく切りのよいアドレスに置くと速度が向上します。16 ビット プロセッサでは、通常、2 で割り切れるアドレスにデータを置くと、アクセス時間が短くなります。→ -alignloc、-alignst

errno

エラーが発生した場合に、エラー コードが格納される int 型の広域変数です。この変数に設定されるエラー値には、定義範囲外の引数が渡されたことを示す EDOM、結果が範囲外になったことを示す ERANGE などがあります。EDOM と ERANGE は ISO/JIS/ANSI 規格です。これらの値は errno.h で E から始まる名前に定義されています。

errno 変数は、スタートアップ ルーチンで 0 に初期化されます。その後、いずれかのライブラリ関数でエラーが発生すると、0 以外のエラー値が書き込まれます。errno の値は、他のエラーで上書きされるか、プログラムで明示的に値を代入しない限り、変化しません。

環境変数

MS-DOS、Windows、UNIX などのオペレーティング システムには、「環境変数」と呼ばれる設定手段があります。一般に環境変数を設定するには、次のように入力します。

set <variable-name>=<value>

環境変数の内容を消去するには、次のように入力します。

set <variable-name>=

環境変数の内容を表示するには、次のように入力します。

set

たとえば、環境変数 lclib に「Light C\lib」を設定するには、次のように入力します。

set lclib=Light C\lib

オペレーティング システムの起動時に環境変数を自動的に設定することもできます。それには、MS-DOS および Windows 95/98 の場合は、起動ドライブのルート ディレクトリにある autoexec.bat に上のうような set コマンドを記述します。Windows NT の場合は、コントロール パネルの [システム] アプレットを使用します。

逆ポーランド記法

演算の対象値を先に、演算子を後に書く記法です。たとえば sizeof a を逆ポーランド記法で書くと a sizeof となり、a + b を逆ポーランド記法で書くと a b + となります。後者は「a と b を足す」と読めるので、日本語の文法に似ています。

コマンド プロンプト

コマンドライン プログラムを実行するためのウィンドウです。Windows XP でコマンド プロンプトを開くには、[スタート] → [プログラム] → [アクセサリ] → [コマンド プロンプト] を選択します。

終了コード (OS 戻り値)

オペレーティング システム (OS) に返される整数で、MS-DOS では 0 ～ 255 です。通常、0 は正常終了を表し、1 以上は異常終了を表します。

作成するプログラムでは、main() の戻り値または exit() の引数で終了コードを指定できます。Light C コンパイラ自体の終了コードは、オプション -rw で指定できます。

MS-DOS では、"IF ERRORLEVEL" バッチコマンドなどを使用して、プログラムの終了コードを判定できます。

ヌル終端文字列 (C 言語の文字列)

末尾に値 0 のバイトが付加された文字列です。通常、C 言語の「文字列」という用語は、このヌル終端文字列を意味します。

多バイト文字列 (マルチバイト文字列)

2 バイト以上で表される文字が混在する文字列のことで、日本で通常使用されている Shift-JIS 文字列は、その一例です。→ ワイド文字列

汎整数拡張 (integral promotion)

サイズが int のサイズより小さい整数を式の中で使用したり関数に渡したりすると、自動的に int または unsigned int に変換されること。次のように変換されます。

変換前 | 変換後
signed char | int
unsigned char | int

たとえば、int func( signed char a, signed char b ) { return a + b; } という関数を func( 127, 127 ) で呼び出すと、a + b は (int)a + (int)b のように計算されるため、結果は -2 ではなく 254 になります。

標準入出力

プログラムで FILE 構造体を使用すると、FILE 関連のライブラリ モジュールがリンクされ、stdin、stdout、stderr、stdprn の 4 つの標準入出力が自動的に用意されます。

名前 | FILE* 型変数 | アクセス モード | DOS ハンドル | 通常の連結先
標準入力 | stdin | "r" | 0 | キーボード
標準出力 | stdout | "w" | 1 | ディスプレイ
標準エラー出力 | stderr | "w" | 2 | ディスプレイ
標準プリンタ出力 | stdprn | "w" | 4 | プリンタ

stdin ～ stdprn は、stdio.h およびライブラリ モジュール fbuf.c で FILE* 型の広域変数として定義されています。いずれもテキスト モードで、stdin 以外はバッファリングされません。
例 | scanf( "%d", &i ); | // 標準入力から取得
 | fscanf( stdin, "%d", &i ); | // 同上
 | printf( "Hello\n" ); | // 標準出力に出力
 | fprintf( stdout, "Hello\n" ); | // 同上
 | fprintf( stderr, "Hello\n" ); | // 標準エラー出力に出力
 | fprintf( stdprn, "Hello\f" ); | // プリンタに出力して改ページ

メモ 標準補助入出力 stdaux は、アクセス モードを一意に決められないため、初期状態では定義されていません。ただし、fbuf.c をコメントに従って編集すれば、簡単に追加できます。

ヘッダー ファイル

#include 文で取り込むためのファイルで、一般にはマクロ定義、関数のプロトタイプ宣言、広域変数の宣言などを行います。

C コンパイラには stdlib.h、string.h などいくつかの標準ヘッダー ファイルが付属しています。

リテラル

リテラル (literal)」とは「そのもの」という意味で、「値そのものを記載したもの」というほどの意味です。整数リテラル、浮動小数点数リテラル、文字リテラル、文字列リテラルがあります。「定数」と似ていますが、「定数」には const 変数も入る可能性があるので「リテラル」という言葉で区別しています。

ホワイトスペース (空白類)

' ' (20)、'\t' (09)、'\n' (0A)、'\v' (0B)、'\f' (0C)、'\r' (0D) のいずれかです。isspace 関数で判定できます。


提供ファイル一覧

Light C は、次のディレクトリ階層に収められています。

bin | 実行ファイル
inc | インクルード ファイル
lib | ライブラリ ファイル
libsrc | ライブラリのソース ファイル

実行ファイル

bin ディレクトリには、次の実行ファイルが収められています。

lc.exe | コンパイラ
lil32.exe | リンカ
lid.exe | デバッガ
llib.exe | ライブラリ マネージャ
lcc.exe | コンパイラ本体 (単独起動不可)
lcasm.exe | アセンブラ部分 (単独起動不可)

lid.exe は、MS-DOS 環境で動作します。それ以外の実行ファイルは、32 ビット Windows のコマンド プロンプトで動作します。

ライブラリ

lib ディレクトリには、次のサブディレクトリがあります。

8086 | -8086 (既定値) で使用
186 | -186 で使用

それぞれの CPU を示すディレクトリの下に、さらに次のサブディレクトリがあります。

small | small モデルで使用
medium | medium モデルで使用
compact | compact モデルで使用
large | large モデルで使用

各ディレクトリには、次のライブラリ ファイルが収められています。llib.exe を使用すると、各 .llb ファイルの内容を確認できます。

std.llb | 共通のライブラリ モジュール
emul.llb | 浮動小数点演算エミュレータを使用するモジュール
fpu.llb | 浮動小数点演算コプロセッサを使用するモジュール
dos.llb | MS-DOS の機能に依存するモジュール
nos.llb | MS-DOS の機能に依存しないバージョン


体験版の制限

体験版は無料で使用でき、全ファイルを改変しない限り自由に配布できます。ただし、次の制限があります。

  • small モデルのライブラリしか付属していません。
  • ライブラリのソース ファイルは付属していません。
  • small モデル以外では、およそ 100 行未満のプログラムのみコンパイルできます。small モデルなら行数制限はありません。

http://www.tamasoft.co.jp/lc/ から最新の体験版をダウンロードできます。


よくある質問 (FAQ)

インストールできない

ここをクリックしてください。

UTK (HEB) 版のコマンド名や生成ファイル名がマニュアルと異なる

次のような違いがあります。マニュアルの説明は、通常版の名前で記載されていることがありますので、すみませんが適宜読み替えてください。

 | 通常版 | UTK 版
コンパイル コマンド | lc | lch
リンク コマンド | lil, lil32 | lilh
アセンブル コマンド | lasm, lasm32 | lasmh
生成される HEX ファイルの拡張子 | .hex | .heb

なお、テキスト形式の .hex ファイルとは異なり、.heb ファイルはバイナリ形式です。

UTK (HEB) 版でリンクすると「未解決の外部参照名」があるとのエラーになる

環境変数 lclib が正しく設定されていること、また -186 を指定していることを確認してください。

UTK (HEB) 版で HEX ファイルを作成しようとすると「未解決の外部参照名「__stack_chk」があります」というリンク エラーが発生する

コンパイル オプション -gs を指定してください。

UTK (HEB) 版で prime.c をコンパイル・リンクすると「未解決の外部参照名「_printf」があります」というリンク エラーが発生する

UTK 版に printf 関数は付属していません。printf 関数は OS (MS-DOS) の表示環境を必要としますが、UTK 版は OS を前提としていません。同様の理由で、fopen、malloc、exit などの OS 依存関数も UTK 版には付属していません。たとえば、仮想的な表示用バッファを確保して sprintf を使用すれば、コンパイル・リンクできます。→ UTK 版でコンパイル・リンクできる prime.c

アセンブラのマニュアルはないか？

http://www.tamasoft.co.jp/lasm/index.html からダウンロードできます。

グラフィック機能は付属しているか？

Light C にグラフィック機能は付属しておりません。

Light C は MS-DOS 汎用のプログラムを作成する C コンパイラですから、MS-DOS の OS コールや PC/AT の BIOS コールを使って線を描画することは可能ですが、そのような関数が付属しているわけではないので、自作するか、または互換性のあるライブラリを別途入手する必要があります。MS-DOS 用のグラフィックライブラリで、C またはアセンブラのソース コードが付属しているものならば使用できる可能性がありますが、そのようなライブラリに何があるか、こちらでは把握しておりません。

SS ≠ DS を前提とするコードを生成できるか？

Light C V1.38 以降では、コンパイル時に -lss を指定することにより、SS ≠ DS (DGROUP) を前提とするコードを生成できるようになりました。

作成したプログラムを Windows XP で実行したとき、何も表示されない (2004/10/21)

一部の Windows XP では、Light C で作成した prime.exe などのプログラムを実行しても何も表示されない場合があります。このような Windows XP では、すべての 16 ビット プログラムで同じ現象が発生するようです。

この場合は、DOS ウィンドウの左上隅をクリックし、[プロパティ] を選択して、[オプション] タブで [全画面表示] を選択してみてください。こうすれば正しく表示されるようになる場合があります。この後、再び [オプション] タブで [ウィンドウ表示] を選択するとウィンドウ表示に戻りますが、それでも引き続き正しい表示が得られるようです。

詳しいことはわかりませんが、Windows XP の問題ではないかと思います。


改版履歴

1.0 1999/08/23
初版
1.01 1999/08/25
register キーワードと /or の併用で起こる障害を修正
コメントなどを微調整
1.02 1999/09/01
float 型の関数引数と戻り値に対応
オプション -segfv を追加
1.03 1999/09/08
_asm を追加し、複数行のインライン アセンブラ ブロックをサポート
_macro を追加し、インライン アセンブラのマクロをサポート
1.04 1999/09/16
割り込みハンドラの記述用に interrupt キーワードを追加
cpu.h を追加し、peekw、pokew、inportw、outportw、int86、intdos、set_vector などの各種低水準関数をサポート
インライン アセンブラで複数の同名局所変数も簡単に使用できるように変更
1.04A 1999/09/17
_macro の引数に #define 定義名を書けるように変更
#include のパラメータに #define 定義名を書けるように修正
_setfcw() を追加
1.05 1999/09/29
割り込みハンドラの記述用に interrupt キーワードを追加
cpu.h を追加し、peekw、pokew、inportw、outportw、int86、intdos、set_vector などの各種低水準関数をサポート
1.05A 1999/09/30
continue 文があると無限ループに陥る障害を修正
1.06 1999/09/30
体験版で small モデルを制限なく使用できるように変更
1.06A 1999/10/22
atof() を追加
? : 演算子に float 型の値を渡したとき、結果が double に昇格変換されないように変更
1.06B 1999/10/30
広域変数の初期値または配列要素の初期値として関数アドレスを参照したとき、アセンブラ コードにその関数名を定義する extrn 命令が出力されない現象を修正
1.1 1999/11/10
デバッグ情報の形式を変更。デバッグ モードを使用する場合、Light C 1.1 以降、LASM 2.2 以降、および LIL 2.2 以降をそれぞれの過去のバージョンと組み合わせて使用することはできません。
void 関数から値を返そうとするコードを警告
1.11 1999/11/19
interrupt 関数の前後で自動的に全レジスタをプッシュ/ポップするように修正
1.12 1999/11/24
#define 名を _asm 内でも使用できるように拡張
複数命令を持つ _asm を #define の値として定義できるように拡張
1.13 1999/11/26
「-segc:<seg>:」により「クラス名なし」を指定できるように拡張
無名の enum (enum { a, b, c }; など) に対応
要素数を明示しない extern 配列 (extern short a[]; など) に対応
同一名に対する struct と union の指定矛盾を検出するように修正
1.13A 1999/12/02
構文「(int)sizeof(n)」を「(int)(sizeof(n))」と書かなくてもよいように変更
1.13B 1999/12/06
-zah を使用できるように修正
ビット フィールドのデバッグ情報をサポート
レジスタ変数のデバッグ情報をサポート
1.13C 1999/12/29
数個以上の広域変数があるとデバッグ モードでリンクできない問題を修正
体験版の制限を変更
1.2 2000/08/04
「a = ! b」をコンパイルできない問題を修正
_asm を関数外にも書けるように強化
配列の初期化リストを「,」で終えられるように強化 (例：int a[] = {1,2,3,};)
デバッグ情報ファイルの PROC レコードに ZA、ZC、ZL の 3 フィールドを追加
1.23 2000/12/04
const 配列をポインタに代入したり、関数の引数として渡せない問題を修正
far 関数を 2 つ以上続けて定義したとき、2 番目以降の関数で es レジスタが初期化されない場合がある問題を修正
大きな switch 文でジャンプテーブルを使用するか指定するオプション -sjt を追加
switch 文のジャンプテーブルが変更可能データ用の dseg ではなく定数用の kseg に生成されるように変更
LIL 2.36 2001/01/31
マップ ファイルの「オブジェクト ファイル別のセグメント始点」に長さ表示を追加。長さ 0 のセグメントを表示しないように変更。
1.24 2001/02/26
ANSI C 規格テストの結果に対応した各種の修正
1.25 2001/02/27
-segfn、-segfc オプションを追加
1.31 2001/10/15
ANSI 互換性テストの結果による各種修正
1.32 2002/01/08
コード セグメントを para アラインにするオプション -csp を追加
1.33 2002/01/10
代入先のポインタの後置インクリメントでポインタが 2 つ進む障害を修正
1.34 2002/01/16
文字型の関数引数にシフト演算式を渡したときの障害を修正
1.36 2002/01/16
他ブロックのラベルに goto で移動できるように変更 → func() { { L:; } goto L; } のようなコードをコンパイルできるようになりました
2 回目以降の fgetc( stdin ) がすぐに返ってきてしまう問題を修正
1.38 2002/04/16
局所変数に SS レジスタでアクセスするオプション -lss を追加
1.39 2002/06/20
次のコードが正しくコンパイルされるように修正
    unsigned int ua[2];
    ua[0] = 3;
    int i = (int)ua[0];
1.41A 2004/04/08
[float 変数] = (float)([整数] - [整数]) の計算について、各整数を float に変換してから減算するのではなく、整数同士の減算を行ってから float に変換するように修正
1.42 2004/06/21
関数引数の扱いを決めるキーワード cdecl_r、syscall_r、stdcall_r、pascal_r を追加。各キーワードの意味は次のとおりです。

修飾子 | "_" の付加 | 引数がスタックに積まれる順序 | スタックから引数を除去する側
(なし) | あり | 後から | 呼び出された側
syscall | なし | 後から | 呼び出された側
stdcall | あり | 前から | 呼び出した側
pascal | なし | 前から | 呼び出した側
cdecl_r | あり | 後から | 呼び出した側
syscall_r | なし | 後から | 呼び出した側
stdcall_r | あり | 前から | 呼び出された側
pascal_r | なし | 前から | 呼び出された側

ヘルプの「関数呼び出し規約」も参照してください。

(1.42) 2006/07/31
オンライン ヘルプ Web 版を作成し、http://www.tamasoft.co.jp/lc/hlp/ で公開しました。
オンライン ヘルプ CHM 版もここからダウンロードできます。
1.42C 2007/02/17
unsigned int または unsigned long を float または double に変換したとき、signed として変換される問題を修正
LIL 2.41 2007/03/02
SYMDEB 形式のシンボルファイルを出力するオプション -msym を追加
lcasm 2007/06/26
変数の初期化子に共有変数と外部変数 (extern) への参照を共に使用したとき、不正な参照アドレスが設定されてる問題を修正 (アセンブラの問題)
1.42D 2007/10/16
「(int)0x8000 >> 1」のように int 型の定数を右シフトしたとき、最上位ビットが 0 になる現象を修正
1.42E 2010/06/30
-lss 指定時に double など大サイズ値の受け渡しが正しくない問題を修正

Copyright © Tama Software Ltd, 1999-2010. ← → 目次 索引


索引

記号・数字 A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
あ行 か行 さ行 た行 な行 は行 ま行 や行 ら行 わ行

記号・数字

* (ポインタ)

%, 書式 ◇

-?

... (引数の省略)

0 終端文字列

-186

32 オプション (LIL) (MINALLOC/MAXALLOC)

3 文字表記

64KB を超えるセグメント

-8086

[ ] (配列)

\ (エスケープ シーケンス)

A

abnormal termination

abort

abs

-ac

acos

-al

-alignloc

-alignst

-am

AMAX オプション (LIL)

AMIN オプション (LIL)

AND

-ansi

-ansicom

-ansidec

-ansikey

_ANSI_KEYWORD

argc

argv

-as

asctime

asin

_asm ◇

_asmcode

assert

atan2

atan

atexit

atof

atoi

atol

auto

B

-bin

BIN 形式

BIN ファイルの作成 (LIL)

break

bsearch

bseg

BUFSIZ

BYTEREGS

B オプション (LIL)

C

-c

C89

[C99]

-ca

calloc

case

c_common

cdecl_r

ceil

char

CHAR_MAX

CHAR_MIN

clearerr

CLK_TCK

clock

CLOCKS_PER_SEC

clock_t

_close

-colc

-cold

-coli

compact

COM 形式

COM ファイルの作成 (LIL)

const

continue

cooked モード ◇

cos

cosh

_creat

cseg

-csp

ctime

C オプション (LIL)

C 言語の文法

D

-d

__DATE__

dbg ファイル

DBL_xxx

default

#define

defined 演算子

DGROUP

difftime

div

div_t

do

DOSSEG

double

dseg

-dspcl

DS/SS レジスタと局所変数

D オプション (LIL)

E

e, 自然対数の底

echo, #pragma

ELA レコード

#elif

#else

else

-emul

#endif

enum

EOF, feof

EOF

-?err

-errcon

-errd

-errmax

errno

ESA レコード

-evall

-evalr

EXE 形式

_exit

exit

EXIT_FAILURE

EXIT_SUCCESS

exp

extern

E オプション (LIL)

F

-fa

fabs

FAR_BSS

_FAR_CODE

_FAR_DATA

far

fclose

-fe

feof

ferror

fflush

_ffree

fgetc

fgetpos

fgets

__FILE__

_filecpy

FILENAME_MAX

FILE 構造体

_find_first

_find_next

_find_t

-fl

float

floor

FLT_xxx

-fm

_fmalloc

_fmemchr

_fmemcmp

_fmemcpy

_fmemicmp

_fmemmove

_fmemset

fmod

_fmrest

-fo

fopen ◇

FOPEN_MAX

for

-fp

_FP_EMUL

FP_OFF

fpos_t

fprintf

FP_SEG

FPU

fputc

fputs

fread

free

freopen

frexp

fscanf

fseek

fsetpos

_fstrcat

_fstrchr

_fstrcmp

_fstrcpy

_fstricmp

_fstrlen

ftell

fwrite

G

getc

getchar

getenv

_getfcw

_getpsp

get_regs

gets

get_sregs

getvect

_getw

-gf

GMT

gmtime

goto

-gs

-> (メンバ参照演算子)

H

-hex

HEX オプション (LIL)

HEX 形式

HEX ファイルの作成 (LIL)

HUGE_VAL

H オプション (LIL)

I

IEEE 浮動小数点数

#if

#ifdef

if

#ifndef

#include

IncludeLib

inportb

inportw

int 21h

int86

int86x

intdos

intdosx

interrupt

inthdlr_t

int

INT_MAX

INT_MIN

_IOxBUF

I/O 関数

I/O ポート

出力

入力

isalnum

isalpha

iscntrl

isdigit

isgraph

_iskana

_iskanji2

_iskanji2nd

_iskanji

_iskmoji

isleadbyte

islower

ISO/IEC

ISO/JIS/ANSI

ISO/JIS/ANSI 規格との互換性

isprint

ispunct

isspace

isupper

isxdigit

_itoa

J

-j

_jis2sjis

JIS

jmp_buf

K

K&R 形式の関数宣言

-kcp

-?key

kseg

L

-l

labs

large

LASM

[LC]

lcasm.exe

lcc.exe

lcinc (環境変数)

LCLIB

lclib

lclib (環境変数)

lcopt

lcopt (環境変数)

_LC_VERSION

ldexp

ldiv

ldiv_t

Light Linker

Light Macro Assembler

lil32.exe

LIL

#line

__LINE__

-linker

LLIB

locale.h

localtime

log10

log

longjmp

long

LONG_MAX

LONG_MIN

_lseek

-lss

L_tmpnam

_ltoa

L オプション (LIL)

M

_macro

main

malloc

-masm

_max

MAXALLOC (LIL)

MB_CUR_MAX

mblen

mbstowcs

mbtowc

medium

_memand

memchr

memcmp

memcpy

_memicmp

memmove

_memnot

_memor

_memrep

memset

_memshl

_memstr

_memxor

_min

MINALLOC (LIL)

_min_stack

MK_FP

mktime

modf

MS-DOS ファンクション コール

_msize

M オプション (LIL)

N

-nc

NDEBUG

near

NE 形式

_nfree

_nmalloc

_nmrest

NOT

NULL

_null_area

null pointer assignment

_nullptr_chk

. (メンバ参照演算子)

O

-o

-oasm

OBJ 形式

-odn

offsetof

-ogc

-oge

-ogl

OMF

-omisc

-onp

_open

-or

OR

-os

[OS]

_OS_NONE

OS 戻り値 ◇ ◇

outportb

outportw

P

-pad

pascal

peekbf

peekb

peekwf

peekw

perror

PE 形式

PFL オプション (LIL)

PF オプション (LIL)

-pi

-pl

pokebf

pokeb

pokewf

pokew

pow

#pragma

#pragma asm

#pragma echo

#pragma segment

prime.c

printf

PSP

ptrdiff_t

-ptrdist

public, セグメントのコンバイン属性

putchar

putc

puts

_putw

Q

qsort

R

R.1000 null pointer assignment

R.1010 stack overflow

R.1100 abnormal termination

raise

RAND_MAX

rand

raw モード ◇

-re

RE0 オプション (LIL)

_read

realloc

register

REGS ◇ ◇

remove

rename

_rest_stack

return

rewind

RL オプション (LIL)

_RND_MINUS

_RND_NEAR

_RND_PLUS

_RND_xxx

_RND_ZERO

ROM 化 ◇

-rw

R オプション (LIL)

S

scanf

SCHAR_MAX

SCHAR_MIN

SEEK_xxx

-segc

-segfc

-segfn

-segfv

segment, #pragma

-segn

setbuf

_setfcw

setjmp

setlocale

set_regs

setvbuf

setvect

short

SHRT_MAX

SHRT_MIN

SIGABRT

sig_atomic_t

SIG_DFL

_sighdlr_t

SIG_IGN

signal ◇

signed

SIGxxx

-silent

sinh

sin

sizeof

size_t

_sjis2jis

-sjt

small

sprintf

sqrt

srand

SREGS ◇

sscanf

SS/DS レジスタと局所変数

_stack_chk

start.asm

static

static 関数

stdcall

stderr

stdin

stdout

stdprn

-stk

strcat

strchr

strcmp

strcoll

strcpy

strcspn

strerror

strftime

_strhcmp

_stricmp

strlen

strncat

strncmp

strncpy

strpbrk

strrchr

strspn

strstr

_strtcmp

strtod

strtok

strtol

strtoul

struct

strxfrm

switch

switch 文のコード化方法

Symbol フォント キャラクタ コード表

syscall

_system

system

S オプション (LIL)

T

-tab

tanh

tan

__TIME__

time

time_t

tmpfile

TMP_MAX

tmpnam

tm

tolower

toupper

TSD オプション (LIL)

typedef

U

UCHAR_MAX

UE オプション (LIL)

ULONG_MAX

_ultoa

#undef

ungetc

union

unsigned

-useas

USHRT_MAX

_utoa

U オプション (LIL)

V

va_arg

va_end

va_list

va_start

vfprintf

vfscanf

void

volatile

vprintf

vscanf

vsprintf

vsscanf

W

wchar_t

wcscat

wcscmp

wcscpy

wcslen

wcsncat

wcsncmp

wcsncpy

wcstombs

wcstrtok

wctomb

Webdings フォント キャラクタ コード表

-wenum

while

Wingdings フォント キャラクタ コード表

-wn

-wncs

-wnt

WORDREGS

_write

X

XOR

Y

Y オプション (LIL)

Z

-zah

-zh

-zi

-zl

zstr (ヌル終端文字列)

あ行

アーク サイン/コサイン/タンジェント

アサート

アスキー コード表

アスキー/シフト JIS キャラクタ コード表

アセンブラ, インライン

アセンブラ

アセンブラ ルーチンとのリンク

値リスト ◇

アドレス

アノニマス構造体

アボート

余り

アライン

アライン (境界整列)

位置, ファイル

一般的なオプション

移動, ファイル

入れ子, コメント

色見本

インクルード

インクルード ファイル検索パス

インストール

インテル HEX 形式

インライン アセンブラ

エコー, #pragma

エスケープ シーケンス

エミュレータ, 浮動小数点演算

エラー

コンパイル/アセンブル/リンク時

ランタイム

エラー、警告、デバッグ オプション

エラー コード (errno)

エラー メッセージ

円記号とバックスラッシュ

演算子

オープン, ファイル

応答ファイル (LIL)

欧文フォント キャラクタ コード表

大文字と小文字を無視して比較

大文字と小文字

押し戻し, ungetc

オフセット, 構造体メンバの

オブジェクト ファイルの形式

オプション

か行

カーニハン リッチー (K&R) 形式の関数宣言

改版履歴

返り値

拡張セグメント アドレス レコード ◇

拡張リニア アドレス レコード ◇

_ (下線) の付加

下線 (_) の付加

型指定子

型修飾子

型定義

型

... (可変個の引数)

可変個の引数 ◇

カラー見本

環境変数, 値の取得

環境変数 ◇

関数一覧

関数へのポインタ

関数呼び出し規約

関数呼び出し

関数

簡単な使用例

外部参照

キーワード

記憶クラス

機械語

起動

基本型

キャラクタ コード表

規約, 表記

境界整列

共用体

局所変数と DS/SS レジスタ

局所変数

切り捨てと切り上げ

逆三角関数

逆ポーランド記法

行継続

クイック ソート

空白類

組み込み用途

クローズ, ファイル

グリニッジ標準時間

グループ

グローバル変数

検索

ファイル

文字列

文字

検索パス

書式 ◇

広域変数

構造体, メンバのオフセット

構造体

コサイン

このドキュメントの表記規約

コピー

ファイル

文字列～関数

コマンドの実行

コマンド プロンプト

コマンドライン形式

コメント

コメントの入れ子

小文字と大文字

こんなときは

コンバイン属性

コンパイル エラーと警告

コンパイル オプション

コンパクト (メモリ モデル)

さ行

再オープン, ファイル

最後の部分の比較, 文字列

サイズ (MINALLOC/MAXALLOC)

最適化オプション

サイレント モード

サイン

索引

削除, ファイル

サブルーチン

サポートされない機能

三角関数

三項演算

三文字表記

残存スタック サイズ

残存メモリ サイズ

式

シグナル関数

自然対数の底

自然対数

シフト JIS コード表

シフト

修飾子

終了コード ◇

出力変換指定子

小数, 関数

省略記号, 引数

初期化コード

初期化子

使用例

指令, プリプロセス

時間関数

字句

実行, コマンド

実行ファイル名の指定 (LIL)

自動選択オブジェクト ファイル

自動変数

ジャンプ

ジャンプテーブルの生成, switch

充填, memset

寿命 (生存期間)

条件分岐

常用対数

剰余 ◇

スコープ

関数

引数

変数

スタートアップ ルーチン

スタック

オーバーフローの検出

サイズの指定

残存サイズ

スタック オーバーフロー

スタックに引数を積む順序

ステートメント

スモール (メモリ モデル)

制御文

整数リテラル

生成ファイルを指定するオプション

生存期間

静的関数

静的変数 ◇

整列 (アライン)

セグメント, #pragma

セグメント名

セグメント名の変更

宣言, 変数

宣言子

宣言

先頭部分の比較, 文字列

絶対値

ゼロ終端文字列

全角文字 ◇

ソース ファイルの記述方法を規定するオプション

ソート

双曲線関数

素数

その他の OS 依存関数

その他の OS 独立関数

ソフトウェア割り込み

属性とラベル (dgb ファイル)

た行

体験版の制限

対数 ◇

タイプ (dbg ファイル)

タイプ

タグ

共用体

構造体

他の高級言語とのリンク

多バイト文字列 (マルチバイト文字列)

多バイト/ワイド文字関数

タンジェント

代入

置換, 文字列

注釈

著作権と連絡先

提供ファイル一覧

定義済みマクロ

定数

const

整数

浮動小数点数

文字列

文字

定数

テキスト モード ◇

適用範囲 (スコープ)

手続き

データ形式

ディレクティブ, プリプロセス

デバッグ情報ファイル

トークン ◇

トークンの切り出し

閉じる, ファイル

トライグラフ

トラブル シューティング

な行

長さ, 文字列

名前の変更, ファイル

名前

並べ替え

二分検索

日本工業規格

日本語表記

入出力関数

入出力先の変更

入力変換指定子

ヌル終端文字列

ネイピア数

ネスト, コメント

は行

配置アドレス

ハイパーボリック サイン/コサイン/タンジェント

配列

はじめに

派生型

汎整数拡張

バイナリ検索

バイナリ モード ◇

バックスラッシュと円記号

パディング

比較, 文字列～関数

比較演算子

引数の受け渡し

引数の順序とアンダースコア (_)

引数のスコープ

引数

表記規約

標準エラー出力

標準出力

標準入出力

標準入力

標準プリンタ出力

開く, ファイル

ビット演算

AND/OR/XOR

NOT

ビット演算子

ビット演算

ビット シフト

ビット フィールド

ファイル

位置

検索

コピー

削除

名前の変更

ファイル形式

EXE/COM/BIN/OBJ

HEX

デバッグ情報

ファイル入出力関数

ファンクション コール, MS-DOS

副作用

浮動小数点演算エミュレータ

浮動小数点演算関数

浮動小数点数, 丸め方向

浮動小数点数リテラル

フラッシュ

フラット セグメント

ブロック

文, 制御

文法概要

文

プール, 文字列

プッシュ バック, ungetc

プラグマ

プリプロセス演算子

プリプロセス指令

プリプロセス ◇

プログラムの最小化

プロシージャ

プロセスの起動

プロセッサ/メモリ直接アクセス関数

プロトタイプ宣言

平方根

ヘッダー ファイルのマクロ定義

ヘッダー ファイル

変換, 書式 ◇

変数, 宣言

変数のスコープ

変数

ホワイトスペース

ポート

出力

入力

ポインタ, 関数への

ポインタ

ポジション, ファイル

ま行

前処理指令

マクロ

アセンブラ

定義済み

マクロ演算子

マクロ

マップファイルの作成 (LIL)

マルチバイト文字

マルチバイト文字列

丸め方向

ミディアム (メモリ モデル)

無名共用体

無名構造体

メイン関数

メモリ

直接書き込み

直接読み出し

メモリ サイズ

メモリの節約

メモリ モデル

メモリ割り当て関数

メンバの参照

文字関数

文字表記

文字リテラル

文字列

検索

コピー関数

先頭部分の比較

置換

長さ

比較関数

末尾部分の比較

連結関数

文字列からの変換関数

文字列操作関数

文字列のプール

文字列への変換関数

文字列リテラル

戻り値の受け渡し

戻り値 ◇

や行

有効範囲 (スコープ)

用語集

よくある質問 (FAQ)

呼び出し規約 ◇

予約語

ら行

ラージ (メモリ モデル)

ライブラリ関数

ライブラリ検索パス

ライブラリの再コンパイル

ライブラリ マネージャ LLIB

ライブラリ マネージャ

ライブラリ

ラベル

乱数

ランタイム エラー

リターンコード, OS

リテラル

整数

浮動小数点数

文字

文字列

リテラル

リンカ LIL のコマンドライン構文 ◇

リンカ LIL

リンカ

リンク

アセンブラ

他の高級言語

ルート

ループ

累乗

レコード (dbg ファイル)

レジスタ値の取得と設定

レジスタの保存

レジスタ変数

レスポンス ファイル (LIL)

列挙

連結, 文字列～関数

ローカル変数

ロケール

ロング ジャンプ

論理演算子

論理積

わ行

ワイド/多バイト文字関数

ワイド文字関数

ワイド文字

ワイルドカードでファイルを検索

割り込みハンドラ

割り込み

Copyright © Tama Software Ltd, 1999-2010. ← → 目次 索引


著作権と連絡先

著作権

Light C for x86 は、多摩ソフトウエア有限会社の製品です。この製品は、同時に利用されるユーザーの数だけ購入する必要があります。この製品で開発したプログラムは、自由に配布、販売していただいて結構です。

ライブラリのソース コードは、自由に改変し、自社の製品または個人のプログラムで利用できます。ただし、ソース コード自体を一般に公開することはできません。

このドキュメントの一部または全部は、自由に転載、複製できます。ただし、転載、複製したドキュメントには、それが Light C のドキュメントからの転載である旨を付記してください。

免責事項

この製品の内容には万全を期しておりますが、この製品を使用した結果の影響については一切責任を負うことはできません。

参考文献

Light C の作成では、次の書籍およびソフトウェア マニュアルを参照しました。

  • JIS プログラム言語 C (JIS X 3010:2003) (日本規格協会)
  • ANSI C 言語辞典 (技術評論社)
  • C 言語による最新アルゴリズム辞典 (技術評論社)
  • プログラミング言語 C (共立出版)
  • 80386 プログラミング (工学社)
  • インテル・アーキテクチャ・ソフトウェア・ディベロッパーズ・マニュアル (インテル株式会社)
  • MSDN ライブラリ (マイクロソフト株式会社)
  • Power C リファレンス (システム・ワン株式会社)
  • 岩波数学辞典 (岩波書店)

多摩ソフトウエア有限会社

ホームページ | http://www.tamasoft.co.jp/
電子メール | info@tamasoft.co.jp
住所 | 〒120-0034 東京都足立区千住 3-6 ツォード千住 壱番館 801
電話 | 03-5813-5563
FAX | 03-5813-5564

Microsoft、MS-DOS、Windows、Windows NT、Windows XP は、米国マイクロソフト社の登録商標です。
Intel、Pentium、MMX は、米国インテル社の登録商標です。


Light C 1.42E for x86

Light C for x86

ISO/JIS/ANSI 準拠 C コンパイラ
Copyright (C) Tama Software Ltd.

はじめに

このドキュメントの表記規約

C コンパイラ

インストール

簡単な使用例

環境変数

コマンドライン形式

コンパイル オプション

一般的なオプション

ソース ファイルの記述方法を規定するオプション

生成ファイルを指定するオプション

生成コードを変更するオプション

最適化オプション

エラー、警告、デバッグ オプション

C 言語の文法

文法概要

文字表記

三文字表記

エスケープ シーケンス

トークン

キーワード、名前、コメント

整数リテラル

浮動小数点数リテラル

文字と文字列

プリプロセス

プリプロセス指令

#pragma

プリプロセス演算子

定義済みマクロ

宣言

変数

関数

型

記憶クラス

型修飾子

ポインタ

配列

構造体

ビット フィールド

共用体

列挙

式と文

式と演算子

制御文

ライブラリ関数

文字列操作関数 (string.h)

文字列への変換関数

文字列からの変換関数

文字関数 (ctype.h)

多バイト/ワイド文字関数 (string.h)

浮動小数点演算関数 (math.h)

時間関数 (time.h)

シグナル関数 (signal.h)

ロング ジャンプ (setjmp.h)

プロセッサ/メモリ直接アクセス関数 (dos.h) [LC]

その他の OS 独立関数

入出力関数 (stdio.h) [OS]

メモリ割り当て関数 [OS]

その他の OS 依存関数 [OS]

入力変換指定子

出力変換指定子

ライブラリの再コンパイル

リンカとライブラリ マネージャ

リンカ (LIL)

リンカ LIL のコマンドライン構文

リンカ オプション

ライブラリ マネージャ (LLIB)

EXE、COM、BIN、OBJ ファイルの形式

インテル HEX 形式

デバッグ情報ファイル

レコード

タイプ

属性とラベル

IEEE 浮動小数点数の形式

資料

仕様

メモリ モデル

セグメント名

関数呼び出し規約

割り込みハンドラ

コンパイル エラーと警告

ランタイム エラー

ISO/JIS/ANSI 規格との互換性

使い方の補足

ROM 化

スタートアップ ルーチン

アセンブラ ルーチンとのリンク

他の高級言語とのリンク

入出力先の変更

プログラムの最小化

互換プロセッサに関するメモ

こんなときは . . .

付録

アスキー/シフト JIS キャラクタ コード表

欧文フォント キャラクタ コード表

Symbol フォント キャラクタ コード表

Wingdings フォント キャラクタ コード表

Webdings フォント キャラクタ コード表

色見本

用語集

提供ファイル一覧

体験版の制限

よくある質問 (FAQ)

改版履歴

索引

著作権と連絡先

Copyright © Tama Software Ltd, 1999-2010. → 目次 索引