ライプラリ編 [ 2 ] 今回は , ライプラリ編といいつつ , ヘッ ダファイルを取り上げます。なにしろ , 今 回が「プリプロセッサ特集」という様相を呈 していますのて、 , どこかてヘッダファイル について触れないわけにはいきません。ま た , ライプラリとヘッダが密接な関係にあ るのはご承知のとおりて、す。 標準ヘッダ ANSI 規格て、は , 以下に示す 15 個のファイ ルが標準ヘッダとして規定されています。 く assert. h> プログラム診断用関数 asse 「 t ( ) を定義する ヘッダて、す。この関数は , マクロ定義によ って実現されており , 直前に非デバッグ指 定用マクロ NDEBUG が定義されていると , void 式となります。 く ctype. h > 文字種別判定用ビットマスク , および判 定用マクロ関数を定義するヘッダて、す。 く errno. h> プログラム実行時におけるエラー情報に 関するマクロを定義します。 く float. h > 浮動小数点型の範囲 ( 数量的限界 ) がマク ロ定義されています。浮動小数点型の特性 は , 処理系および実行環境に依存しますが , 通常 , 旧 EE の浮動小数点演算規格に準拠し たものになります。つまり , MS-DOS の処 理系て、は , インテルの 8087 ( 287 , 387 ) のス ペックと同一になります。 く limits. h> 整数型の範囲 ( 上限値と下限値 ) , 特性 ( 処 理系に依存する ) がマクロ定義されていま す。 c h a 「 , s i n g e d c h a r , u n s i g n e d char, short, unsigned short, int, unsigned int, long, unsigned long の各タイプにつ いての定義が行われていますが , 将来的に は , マルチバイトキャラクタについての定 義が追加されるて、しよう。 く loca . h > プログラムが使用される地域別 ( 国別 ) に 異なるて、あろう処理を行うためのマクロが 定義されています ( 具体的には , 通貨の単位 / 表示形式 , 日付や時刻の表現形式などて、 す ) 。 ANSI 規格て、は , 処理系 ( 地域 ) ごとに 必要な情報を LC て、始まるマクロ名として , このヘッダに追加することが許可されてい ます。混乱を避けるため , ューザプログラ ム内て、は LC て、始まるマクロ名を使用しない よう心がけたほうがよいて、しよう。 く math . h > 数学関数 ( 平方根 , 対数 , 三角関数など ) のプロトタイプが行われています。 く setjmp. h> 非局所的な分岐 ( C の制御構造以外の分 岐 ) を行うための関数 , s mp ( ),longjmp( ) などが定義されています。 く signal.h> シグナル操作 / 処理 ( signal( ) , raise( ) ) に 関するマクロが定義されています。このヘ ッダて、は , S , SIG て、始まるマクロ名が予 約されています。通常 , シグナル処理は , 処理系 , そしてオペレーティングシステム に依存しますのて、 , S 給マクロが追加される 可能性があります。ューザプログラム内て、 は S 旧て、始まるマクロ名を使用しないほうが よいて、しよう。 く stdarg. h> 不特定数個の因数を処理する関数のため のマクロ定義を行います。このヘッダて、定 義されている va list, va arg( ) , va end(), va sta 「 t ( ) などのマクロ定義 , マク TbI.2 <string. h> の予約された関数名 WCS—- 文字列操作用 メモリ操作用 ワイド文字列操作用 ロ関数は , 可変個の因数をもっ関数 (printf( ) など ) のポータビリティを高めるためのもの て、す。 く stddef. h> く stdio. h> 標準入出力のためのマクロ定義 , プロト タイプを行うへッダて、す。 く stdlib. h> 一般的な ( 汎用の ) 標準ライプラリ関数の プロトタイプ , および ?TYPEDEF を行います。 < stdio. h> と合わせてもっとも使用頻度の高 いへッダて、しよう。 く string. h> 文字列操作のための関数のプロトタイプ を行います。このヘッダて、は , Tbl. 2 の文字 列て、始まる関数名が予約されています。 TbI.2 に該当する関数名は , ューザプログ ラムまたは , ユーザのライプラリて、は使用 しないほうがよいて、しよう。 く time. h > 時間に関する処理を定義します。 ANSI 規 格の時間処理用関数は , グリニッジ標準時 を基準として処理されます。実際にユーザ が使用する地域時間 , 季節時間などに関し ては処理系に依存しています。 以上のヘッダファイルによって定義され ている ( 標準的な ) マクロ , および TYPEDEF を TbI. 3 にまとめます。 準標準ヘッダ 以下に示すヘッダは , ANSI 規格て、は定義 されていませんが , PragmaC において標 準とする ( または予約する ) ものて、す。 く conio. h> コンソール入出力 ( ストリームて、はない ) , I / O ポートへの入出力関数を宣言します。 く direct. h> ディレクトリ操作に関する関数を宣言し ます。 く dos. h > MS-DOS のファンクションコールに関連 する関数を宣言します。また 8086 のセグメ ンテーションと C のポインタとの変換用マク プロジェクト PragmaC 43
朝 0 0 の朝 制作プロジェクト オリジナル C コンバイラ もあって , 本稿全体が「プリプロセッサ特集」といっても過言で 今回は , スタンドアローン型のプリプロセッサを作成すること 先月号からスタートしたプロジェクト PragmaC の第 2 回目です。 第 2 回スタンドアローン型プリプロセッサの作成 はない構成になっています。 藤井保則 書式 1 ) のフォーマットの場合 , 指定され たファイルを , 処理系によって定義された ヘッダディレクトリから検索します。 書式 2 ) のフォーマットの場合には , まず , 現在処理中のソースファイルが存在するデ ィレクトリが検索され , 次にヘッダディレ クトリが検索されます。 ・ #define #definei' ィレクテイプはマクロの定義を 行います。 書式 1 ) は , 単純なトークンの置き換えを 行います。 書式 2 ) は , 引数をもっマクロ ( マクロ関数 ) の定義を行います。この形式のマクロ定義 を使用する場合には , 以下の点について注 意しなければなりません。 40 CMAGAZINE 19 6 ァイルの読み込み / 挿入を行います。 #include ディレクテイプは , 指定されたフ ■ #include お , 書式については Tbl. 1 にまとめました。 レクテイプについての簡単な解説てす。な 規格て定義されているプリプロセッサディ ( 命令 ) について定義します。以下は , ANSI まず , プリプロセッサのディレクテイプ プリプロセッサディレクテイプ いいてしよう。 い ) C プログラムは , 存在しないといっても プロセッサを通さない ( その機能を使用しな 部てはありません。しかし , 実際にはプリ プリプロセッサは本来 , C 言語の仕様の一 言語仕様・規約編 [ 2 ] * マクロ名と左側のカッコの間に空白 が存在してはならない * 定義時と使用時の引数の数は一致し ていなければならない ・ #undef #undef ディレクテイプは ,#define ディレ クテイプて、定義されたマクロを無効にしま す。 通常 , 対象となるマクロ名は事前に定義 されているはずて、すが , 未定義の場合て、も ェラーにはなりません。 ■ #if, #elif, #else, #endif #if, #elif, #else, #endif の各ディレクテ イプを使用することにより , 条件プロック の構成 , 条件つきコンパイルを行うことが てきます。 #if および # e ⅱ f ディレクテイプて、は , 指定さ れた条件式の評価値が真 ( 0 以外 ) て、ある場合 にのみ , 後続のテキストプロックの処理が 行われます。 # 引 se ディレクテイプて、は , 直
通常 , # e 「「 0 「が実行されたことにより , 処理 系の作業が中断されることはありませんが , それによって引き起こされる結果について は定義されていません。 # ディレクテイプだけの行 ( # て、始まり , す ぐに行末の行 ) は , 空白行として処理されま す。この結果として発生する唯一の効果は , LINE マクロて、示される行番号がインク リメントされることだけてす。 ■ #pragma #pragma は , プリプロセッサ , そしてコ ンパイラに拡張機能を付加するために定義 されているディレクテイプて、す。従来の C 処 理系て、は , 独自のディレクテイプをもつも のが存在していましたが , ANSI 規格に準拠 する処理系て、は , すべて #pragma ディレク テイプて、実現されることになります。 通常 , #pragma の書式は , #pragma プ ラグマ命令パラメータの形式になります が , その仕様についての定義は行われてい ません。標準的なプラグマ命令というもの は規定されておらず , プラグマ命令によっ て引き起こされる効果については , 完全に 処理系依存となっています。ただし , 各処 理系は理解てきないプラグマ命令に出会っ た場合には , 無視する ( 何もしない ) ことに なっています。 ANSI 規格に適合する処理系のプリプロセ ッサて、は , 上記以外のディレクテイプが存 在することは ( おそらく恒久的に ) 許されま せん。プリプロセッサ機能の拡張が行われ る場合には , すべてプラグマ命令として処 理されることになります。 プリプロセッサ演算子 ANSI 規格て、は , 前述の defined 演算子の ほかに , ふたつのプリプロセッサ演算子 , # と # # が定義されています。これらは , 厳密 な意味ての演算子て、はありませんが , プリ プロセッサ処理行のトークン内にのみ存在 てきるものて , 以下のような効果を引き起 42 CMAGAZINE 19 6 こします。 ・文字列生成 プリプロセッサ演算子 # は , 後続のトーク ンから文字列リテラルを生成します。 以下のようなマクロ定義が行われた場合 , #define message(s) puts(#s) message(HELLO) ; は , puts("HELLO"); ・トークン連結 に展開されます。 12 : 55 : 31 しています。 開始された時刻を文字列リテラルとして表 TIME は , DATE と同様に処理が ・ TIME__ ての厳密な規定は行われていません。 のように展開されますが , その内容につい Jun 15 1990 しています。通常 , このマクロは , 開始された日付を文字列リテラルとして表 このマクロは , 現在行われている処理が ■ _DATE_ て規定されています。 が処理系によって定義されているものとし ANSI 規格て、は , 以下に示す 5 個のマクロ 処理系定義マクロ 成と連結を利用した場合の例を示します。 るものて、はありません。 Fig. 1 ー C に文字列生 のて、あり , プログラマがアクテイプに用い 生成機能のトリック用に用意されているも ただし , この連結はおもに前述の文字列 開が行われます。 行われます。具体的には Fig. 1 ー B のような展 は , Fig. I-A のような形式て、文字列の連結が りませんが , ANSI 規格のプリプロセッサて、 演算子として用意されているわけて、はあ ■文字列連結 va 旧 e ( 12 , 34 ) は , 12E34 に展開されます。 #define value(n , e) n##E##e 以下のようなマクロ定義が行われた場合 , トークンを生成します。 クンと右辺のトークンを連結し , ひとつの プリプロセッサ演算子 # # は , 左辺のトー のように展開されますが , ー DATE ーと同じ くその内容については規定されていません。 現在処理されているソーステキストの行 番号を 10 進数の正数定数として表します。 現在処理されているソーステキストのフ アイル名を文字列リテラルとして表します。 ・ _STDC— このマクロは , 通常 , 10 進正数定数の 1 に 展開されはす。もし , ほかの値に展開され るか , このマクロが定義されていない場合 には , その処理系が ANSI 規格に適合してい ことを表しています。 以上の処理系定義マクロは , #define, # undef ディレクテイプて、定義 / 変更 / 削除する ことはて、きません。ただし , LINE およ び FILE の値については , # ⅱ ne ディレク テイプによる変更が可能て、す。 コメントの除去 プリプロセッサは , 入力されたソーステ キストに含まれるすべてのコメント文字列 を除去します。実際の処理は , コメントと して認識された文字列を 1 個の空白に置き換 えることて、行われます。 Fig. 1 文字列連結 ”文字列 1 ””文字列 2 ” "Good" "Morning" GoodMorning #define pv(), v) printf( #f ” \ n ” , v) pv(%d, 13 ) , ↓ printf(#%d ” *n", 13 ) ; ↓ printf("%d" ” *n", 13 ) ; ↓ printf( ” %d*n", 1 3 ) ;
れていたものて、す。既存の C のソースリスト のほとんどて、は , このディレクテイプが頻 繁に使用されているのを見かけます。 ひとつ , 例をあげてみましよう。 #ifndef NULL #define NULL ((void *)O) #endif これは , ヘッダファイルの中て、よく行わ れている NULL ポインタの値の定義て、すが , 実際には , 少しオールドファッションて、あ るといえます。なぜなら ANSI 規格の処理系 て、は , 以下のようにコーティングすること が可能だからて、す。 #if !defined NULL # ifdef, # ifndef #define NULL ((void) * ) 0 ) 書式 l) 書式 2 ) #endif ANSI 規格の処理系て、は , #ifdef, #ifndef #line を使用する代わりに , #ifi•ィレクテイプと 書式 defined 演算子および論理演算子を使用して # er 「 0 「 同様の効果が得られるわけて、す。 # e 「「 0 「トークン 書式 ■ #line # ⅱ ne ディレクテイプは , 処理系によって 前の # if または #elif( もしくは後述の #ifdef, 意してください 保持されている , 現在処理中のソースリス # ifndef ) の値が偽て、あった場合にのみ ; 後続 また , 条件式内て、は , 通常の C 言語の演算 トについての情報 ( 行番号 , ファイル名 ) を のテキストプロックが処理されます。 子とともにプリプロセッサ演算子 defined が #if および # e ⅱ f ディレクテイプて、使用される 変更するために使用されます。 使用て、きます。 defined 演算子は , 直後に指 このディレクテイプがプリプロセッサに 条件式は , 正数定数式て、なければなりませ 定されたマクロ名が既定義て、あるかどうか よって処理されると , 指定された行番号が ん。ただし , その定義は C 言語 , コンパイラ をチェックするものて、 , 次のように使用し 処理系定義マクロて、ある凵 NE に , また の仕様と必ずしも一致するとは限らない ます。 ファイル名が FILE に , それぞれ代入さ とに注意してください。プリプロセッサの #if defined STDC この例て、は , マクロ名 __STDC が定義 条件式て、は , 型宣言やキャストを行うこと れます。 行番号は , 10 進正数定数て、指定されなけ はて、きませんのて、 , 以下の例のような場合 , されている場合 , 真となり , 未定義の場合 ればなりませんが , 無効な値が指定された どのような結果が引き起こされるかは処理 には偽と評価されます。 場合の動作は規定されていません。また , 系に依存します。 ■ #ifdef, #ifndef ファイル名は 2 重引用符に囲まれた文字列 #define MAX 32767 #ifdef および # ifndef は , 指定されたマクロ て、あれば , たとえそれが DOS のパス名とし #if MAX 十 1 > 0 名が定義されているか ( # ifdef ) , 未定義か ( # て無効なものて、あってもエラーとはなりま この場合 , もし , 計算が unsigned て、行わ ifn def) によって条件判断を行うディレクテ れていたならば , MAX = 32767 , 32767 十 1 = イプて、す。 せん。 32768 , 32768 > 0 となり , 条件は真となり ■ # e 「「 0 「 条件プロックの構成については , 前述の # e 「「 0 「ディレクテイプは , プリプロセッサ ますが , 16 ビットの signed として計算され #else, #endif を使用することがて、き , #ifdef に対してエラーメッセージの出力を指令し た場合には , 32768 = 0x8000 = ー 32768 とな て、はマクロ名が既定義の場合に , #ifndef< り , 条件は偽となります。 MS-DOS 上の処 ます。 は未定義の場合に真のプロックが処理され 理系ては , ほとんどの場合 , 後者の評価が この形式のプリプロセッサ行が評価され ます。 行われますが , ソースリストのポータビリ ると , # erro 「の直後の空白につづくトークン #ifdef および #ifndef は , 条件処理ディレク ティ面から考えると問題が残りますのて、注 から行末まてが標準出力に書き出されます。 テイプとしては , もっとも古くから装備さ プロジェクト PragmaC 41 TbI.I プリプロセッサティレクテイプの書式 #include #include くファイル名 > 書式 l) #include ”ファイル名” 書式 2 ) # define 書式 l) 書式 2 ) # undef 書式 マクロ名 #undef # if, # elif, # else, # endif 書式 マクロ名トークン # define #define マクロ名 ( 引数リスト ) トークン 真真偽 ククク ツツツ ロロロ プブプ トトト ススス キキキ テテテ 式式 条条 は O Q) O マクロ名 # ifdef #ifndef マクロ名 #line 行番号”ファイル名”
Fig. 2 マクロ展開 A ( 正常な ) 展開 test(C マガジン ); ↓マクロ展開 puts()C マガジン # # です ) ; ↓ # # による連結 puts( # C マガジンです ) ; ↓ # による文字列化 puts ( " C マガジンです " ) ; B 現実的な展開 test(C マガジン ) ; ↓マクロ展開 puts ( # C マガジン # # です ) ; ↓ # による文字列化 puts()C マガジン ' # # です ) ; ↓ # # による連結 puts に C マガジン”です ) ; マクロ展開時における再処理は , 再帰的 に行われるわけて、はありません。もし , 再 帰的な手法て、処理が行われるとするならば , 以下のような定義を行った場合に処理系は ハングアップしてしまうて、しよう。 #define A B #define B A X = A 実際の処理においては , はじめに X = A が X = B に変換され , 再処理によって X = B が x =A に変換されます。当然 , もう一 度再処理が必要かどうかの判定が行われま すが , A → B の展開はすて、に行われている ものとして扱われ , 無限再帰ループに陥る ことはありません。 [ 注 ] マクロ展開における再処理 , 引数リ ストの処理などについては , ANSI 規格でも 明確にされておらず , 混沌としたままにな っています。 カスタマイズ 現在の CPP には , ANSI 規格に準拠するプ リプロセッサとしての基本的な機能のみが 装備されています。実際の使用を考えた場 合には , いくつかの拡張機能 , たとえばコ マンドラインからのマクロ名の定義機能な どが必要となるて、しよう。これらについて あります。当然 , 後者の場合には , パーサ ーの段階て、構文工ラーが発生することにな ります。 PragmaC ては , 後者の方式を採用しま す。これが正しいとはいい切れませんが , 一般的てあることは確かて、す。 CPP におけるマクロ展開処理の流れは , 以下のようになっています。 * 置き換え文字列の判定 テキストに含まれるトークンに対して置 き換えが必要かどうか判定し , 必要があれ ば置き換えます。 * # による文字列化 置き換えられたマクロトークンにおいて 文字列化が指定されていた場合には , その トークンを解析し , 場合によっては変換 ( \ → \ \ , " → \ " ) を行いながら文字列リテラルを 作成します。 * # # による連結 置き換えられたマクロトークンにおいて 連結が指定されていた場合には , 連結を行 い , 新しいトークンを作成します。 トークン 46 CMAGAZINE 19 6 * 引数リストの置き換え 展開されたマクロ引数に対して置き換え が必要かどうかを判定し , 置き換えます。 * 再処理 展開されたマクロトークン ( 群 ) に対して , 再スキャンを行います。 * 文字列の連結 ”の形式の隣接する文字列リテラル を結合します。 Prag maC 制作委員会読者委員募集 「プロジェクト PragmaC 」は , まったく新しい C コンバイラの制作を目的とするとともに その制作にあたって広く読者のみなさまと 協議 , 意見交換することをも目的としてい ます。つきましてはこ・意見 , ご要望を文書 , または FD にて下記「プロジェクト PragmaC 」 係までお寄せください。お寄せいただいた こ・意見は , 可能なかぎり PragmC 制作に反映 してまいります。 さらに , ご応募されたみなさまのなかか ら , pragmac 制作委員会読者委員を選考させ ていただき , 読者代表の PragmaC 制作主要メ ンバーとして参加していただく予定です。 宛先 〒 1 02 東京都千代田区九段南 2 ー 3 ー 26 井関ビル 日本ソフトバンク C マガジン編集部 「プロジェクト PragmaC 」係
動させることを目的としたプロトタイプ版 て、あり , 将来 ( ライプラリの作成段階て、 ) 変 更されるて、あろうことをおことわりしてお きます。 また , 補助的なヘッダ ( たとえば < MATH. H > など ) や , 漢字処理用のヘッダ ( たとえば < jctype. h> など ) が増設される予定て、す。 プログラム編 [ 2 ] CPP : C Pre Processor CPP は , スタンドアローンのプリプロセ ッサて、す。 現在 , 市販されている C コンパイラバッケ ージの多くて、は , コンパイラの一部として プリプロセッサが内蔵されており , スタン ドアローンのプリプロセッサを付属させて ごく一部のものに限られている いるのは , ようて、す。て、は , なぜ , この Project PragmaC て、はスタンドアローンプリプロセッサを用 意するのて、しようか ? それはたんに , 予 定されているほかのユーティリティのため に必要だ , という単純な理由て、す。関数の クロスリファレンスを作成したり , 広域変 数のリストを作成したりする単純なユーテ ィリティて、あづても , その入力となるソー ステキストはプリプロセス処理が行われた ものて、ある必要があるからてす。 もちろん , スタンドアローンプリプロセ ッサには , 実用的また教育的な面て、の有効 性もあります。とくに複雑な条件設定など が行われているソースのデバッグ , 解析な どには役立っことて、しよう。 操作方法 CPP は以下に示すとおり , DOS のコマン ドラインからファイル名 ( パス名 ) を指定し て起動を行います。 cpp ファイル名 現在のバージョンて、は , オプションスイ ッチはありませんのて , ファイル名のみが 唯一のパラメータになります。 ただし , CPP の起動に際しては , ヘッダ ファイルが存在するディレクトリを指定す るための環境変数 PCINCLUDE が事前に設 定されていることが前提になります。 CPP のプログラムは , Tbl. 5 にまとめたフ ァイルから構成されています。以下にそれ らを簡単に説明します。 CPP. C プログラムの構成 保持するための ID が追加されています。 語句解析用構造体に行番号 , ファイル名を プリプロセッサの機能に合わせるために ほば同じ働きをする語句解析ルーチンて、す。 回使用した CCTOKEN. H, CCTOKEN ℃と CPTOKEN. H および CPTOKEN ℃は , 前 CPTOKEN . H CPTOKEN . C て、す。 クロ定義の登録 , 展開を行うサプルーチン CPMACRO. H および CPMACRO ℃は , マ CPMACRO. H CPMACRO. C ようにしてください い場合には , 標準出力をリダイレクトする なっています。処理結果をファイルにした 行って , 結果を標準出力に書き出すように ァイルを読み込み , プリプロセッサ処理を CPP は , コマンドラインて、指定されたフ スファイルて、す。 CPP ℃は , CPP プログラムのメインソー CCTYPE. H および CCTYPE. C は , C 言語 の構成文字を判定するための関数やマクロ を定義します。 . 内容は , 前回に使用したも のとまったく同一て、す。 マクロ展開について プリプロセッサを作成しようとする場合 にもっとも問題となるのは , 処理の流れ , とくにマクロ展開と # , # # などの演算子の評 価順序て、す。 プリプロセッサが処理すべき事項を大ま かなフェーズにわけると以下のようになる て、しよう。 * ディレクテイプ行の判定 / 実行 * マクロ展開 * # 演算子による文字列化 * # # 演算子による連結 * コメントの除去 とくに # と # # の評価順序は , 大きな問題と なります。以下のような定義 , 呼び出しが 行われた場合 , #define test(s) puts(#s## て、す ) test(C マガジン ) ; もし , プリプロセッサが , 「マクロ展開→ # # による連結→ # による文字列化」の順序て、評 価を行うとするならば , この例のテキスト は Fig. 2 ー A のように ( 正常に ) 展開されていく はずて、す。 しかし , 実際には , Fig. 2 ー B のように展開 する処理系が多い ( ほとんどの ) ようて、す。 この場合 , 処理系によっては , # # による 連結を行う段階て、エラーとするものもあり ますし , ただたんに無視してしまうものも CCTYPE. H CCTYPE. C TbI.5 CPP プログラム構成 CPP. C CPMACRO . H CPMACRO . C CPTOKEN. H CPTOKEN. C CCTYPE. H CCTYPE. C CPP メインプログラムソース マクロ処理ルーチン用へッダ マクロ処理ルーチンソース 語句解析ルーチン用へッダ C 文字タイプ判定ルーチンソース C 文字タイプ判定ルーチン用へッダ 語甸解析ルーチンソース プロジェクト PragmaC 45
工ル江ス・アイジャパン fo 「 m 面 on from ( 0 pi 「「 5 し引 C -86 し引 C -80 ■ Q&A 0 イプラリを作ったり , 自分好みの コンパイラドライバを作ったりす ることもてきます。また , C 言語初 て、展開します。このマクロはおも の式の値を計算し結果を 10 進数 学えます。するとこのマクロはそ とつだけもち , そこには定数式を マクロ eval はパラメタをひ 開されます。 3142 行目だとすると , ListI ー②と展 出しのあるのがファイル f00. c の たとえば , List1- ①は , assert 呼び 行番号 ( 10 進数 ) に展開されます。 は , 現在読み込んて、いるソースの 展開されます。また , LINE るソースのファイル名 ( 文字列 ) に FILE は , 現在読み込んてい 義されています。 プロセッサによってあらかじめ定 いくっかの特殊なマクロはプリ す。 り知られていない機能を紹介しま れらのほかに cpp がもっているあま ifdef,#if) などを行うことてす。 include), 条件つきコンパイル ( # 換え , ファイルの取り込み ( # くて、てくるマクロ (#define) の置き 具体的な前処理とは C 言語てよ るのもおもしろいかもしれません。 造して新しいユーティリティを作 セッサとしても使えます。これを改 め , たとえばアセンプラのプリプロ いますが , C 言語から独立するた cpp はコンパイルの前処理を行 A るものですか ? プリプロセッサ cpp とは何をす 0 るのて、はないて、しようか。 は C 言語を修得するうえて参考にな 心者には , これらのソースコード List 1 ー 円し E_ : 引 se \ printf("Xs Xd:assertion faiIedYn" #def i ne if (cond) assert(cond) assert (p List 1 ー ( 2 ) List 1 ー ( 3 ) #def i ne #def i ne #def irie N 乢い : リを使用するにあた 152 CMAGAZINE 19 6 テムに合わせて変更し , 新しいラ ソースコードをターゲットのシス ROM 化の場合にはライプラリの す。 コードを再利用することがて、きま 用者は , 安心してこれらのソース かえありません。したがって , 使 ラムを販売してもまったくさしつ 部を引用して新しく作ったプログ 雑誌へ掲載したり , 変更または一 たとえば , 他人に譲渡したり , ん。 扱いにはいっさい制限はありませ す。これらのソースコードの取り ードがパッケージに含まれていま ティリテイプログラムのソースコ lcc, プリプロセッサ cpp などのユー ール make, コンノヾイラドライノヾ プラリのほかにプログラム保守ツ ースコードが , LSI C ー 86 て、はライ LSI C ー 80 て、はライプラリのソ A すが , 取り扱いに制限はあります どのソースコードが付属していま パッケージ中にライプラリな 0 間題はありません。 プログラムを販売してもまったく ルし , ライプラリがリンクされた 必要ありません OLSI C てコンパイ ロイヤリティなどはいっさい しようか ? って , ロイヤリティは必要なので : else printf("Xs Xd:assertion faiIedYn" = NIJ しい ” f00. C ” 燔” #v ” \ n つ , 3142 ) : bar(), の foo(x) V 5 List 1 ー④ foo(V + 3): printf("the val ue of bar(x, eva ー にプリプロセッサのデバッグ用に っくられたのて、すが , インライン 関数て、も使われています。 List1- ③は , List1- ④のように展 開されます。 ・ユーザみなさまへ ◇登録カードの返送はお早めに 返送された「登録カード』をも とにバージョンアップのご案内 , 新製品情報 , 特別割引価格のご案 内などをお送りしております。現 在は LSI C ー 80 のユーザに MS ー DOS クロス , ソースレベル , デバ ッガ LDB ー 80X のご案内をさしあげ ておりますのて , 添付『登録カー ド」をぜひご返送ください ◇住所 , 担当者変更について 登録された住所 , 所属や担当者 などが変更になる場合は , 添付「技 術サービスカード」て変更のご連 絡ください。変更内容を記入のう え , ファクシミリまたは郵便にて お送りください prinf("the value of 5 十 3 is 8 \ n ” ) : ◇技術的なお問い合わせについて 技術的なお間い合わせは添付「技 術サービスカード」をご利用くだ さい。必要事項を記入の上ファク シミリまたは郵便にてお送りくだ ・「 L C -86 試食版」の配布 大好評をいただいております 「 LSI C ー 86 試食版」 ( 「 C マガシン」 創刊号特別付録 ) を 3 , 000 円にて提 供いたします。創刊号を買い損ね た皆様 , ぜひこの機会にご注文く ださい 「 LSI C ー 86 試食版」ディスクに は , read. me ( 試食版仕様の手引 ) , LSIC86. man ( 試食版用マニュア ル ) , order ( 申込購入書 ) が含まれ ております。 申込先〒ー引 東京都渋谷区千駄ヶ谷ト 8 ー 14 工丿レ・エス・アイジャノヾン 「 L C ー 86 試食版」係
ßrief—l ロ FuII Screen Editor ENEC PC9801 E ( 漢字 ROM が必要 ) PC9801 F/M/U/ UV/VF/VM/VX/ UX/LV/CV/RA/ RX/LS/LX/ES/ EX/RS PC9801 XL/XL2/RL ( / ーマルモードのみ ) 旧 M PC の トッフセールスに輝く 工デイターが日本で 4 機種対応から 5 機種対応へ、さらに 広がった Brief の世界 J ー 31 00 SS/SL/GT/ GX/SGT J ー 3300 30 / 50 ( モノクロ・モードのみ ) AX シリーズ / ヾソコン ・ 55 ウインドウ、無限のファイル数 ウインドウは縦橫自由に、 55 まで開くことができま魂また、同時に編集できるファ イルの数や大きさには制限がありません。ひとつのファイルの複数の部分を、そ れぞれ別のウインドウ上で同時に編集することも可能です。 ・プログラミング ◆キー操作ひとつでコンバイルが可能。またプログラムにエラーがあれば自動 的にその箇所へ移動。◆メモリー不足の場合、 Brief は自分の始どをディスク に待避させメモリースペースを開放。◆ ; やなどに対応した高度なインデント もサポート。◆ C 言語のテンプレート編集機能で、 if 文や wh ⅱ e 文等の構文を自 動生成。 ・安全編集 Brief は、一定時間キーを操作しない場合、その時点の編集内容をファイルに 自動保存します。万一、編集中に電源が切れても、最新の保存ファイルから 最小の手間で復旧することができます ◆パッファ書出 / 切換 / 削除 / リスト表示◆ファイル名の 指定 / 表示 / 変更◆パックアップ保存◆特殊文字入力 ◆ 2 行を 1 行に連結◆ファイル単位の挿入◆増分検索 ◆各種マーグ始・終点の入換◆プロックのカット / コピ ー / ペースト / 印刷 / 保存 / 左右へのシフト◆対応する括 弧へ移動◆ C 言語のコメント化 / 非コメント化 / DOS コマンドの実行 / 繰返し◆キー操作記憶 . 面 ◆入力ヒストリー◆英文テキスト整形◆タブの スペース挿入◆拡張子毎に異なった設ィ 定ができるタブ◆検索置換 / 汐ーンの 画面からの入力◆英字の大小文字変換 その他 革命的マルチマシン・エテイター 一本の Brief を AX 協議会・東芝・ NEC ・ IBM ・富士通の 5 メーカー 8 ラインの機種にインストールできますいずれの機 種でも日本語 DOS で縦横無尽の威力を発揮します。 = ~ オビニオンリーダー誌のこの評価 ・プログラミング向きの工ターを探している人は、もう探す必要はないす Jerry PourneIIe (BYTE) 竃鬻第 ・ Brief はプログラマーに最適なだけでなく創造力をかきたてる何物かがある。 Computer World ・ほとんど完ぺきにカスタマイズできるだけの拡張性がある。 Computerla nguage ・まるで夢のようなアンドゥだ、おもわす間違うのを期待しまいそうだ -The C U sere Uournna にを。 = 誉 ・強力無比一マクロ言語 マクロは、極めて強力な表現能力と柔軟性を持った、完成度の高い構造化言 語です。日本システムでは販売後の Brief にも新しいマクロを提供、利用者間の マクロの交流を図り : 編集環境のグレードアップを支援し続けます ・ 300 回ものアンドゥ Brief では各ファイルごとに 3 までの操作を元に戻すことができますのでやり 直しの面倒を気にせ安心して編集できます削減や置換、別のファイルの挿 入など、ほとんどの編集結果をひとつの操作で元に戻せます 0 全機種対応バッケージ ちインチ 2DD と 3.5 インチ 2DD の FD を一挙に同梱。これ以外の メティアの場合はご請求ください。 日ホシステム槽式会社 ・お問い合せは 東京都立川市曙町 1 ー 18 ー 2 ー清ビル立川事業所 Brief ユーザーサ・ポート係 電話 0425 ー 23 ー 4469 FAX 0425 ー 27 ー 6127 ( 消費税は含まず ) 48 , 000 円 Brief は Under Ware 社の商標てす。
に教えます。これによって , PWB はコンパ イラやリンカのオプションの初期値を決め ます。オプションは , デバッグバーション 用とリリースパージョン用の 2 種類が登録さ れます。ューザは PWB が決めたオプション の修正を , メニューの選択て、簡単に行うこ とがて、きます。変更されたオプションは , PWB が自動的に MAKE ファイルに反映して くれます。 いよいよコンパイルて、す。デバッグが終 わるまて、は , デノヾッグノヾーションて、コンノヾ イルします。 PWB は , コンパイル終了後に 工ラーまたは警告があると , コンパイル結 果のウインドウにエラーまたは警告を表示 して , それが発生したソース行にカーソル を移動させます。 MS-C Ver. 6.0 て、は警告 レベルが 0 から 4 まて、あり , 4 にすると LINT ユーティリティのように細かいところまて 警告を発して , 不用意なミスや移植性の悪 い部分を指摘してくれます。 コンパイル / リンクが無事に終了すると , デバッグに移ります。 PWB のメニューて、デ バッグを選択すれば Code View( コードビ ュー ) が起動され , 終了すると PWB に戻り ます。デバッグ作業中は , プログラムの修 正とコンパイルの繰り返して、すが , MS-C Ver. 6.0 には QC と同様のクイックコンパイ ル , インクリメンタルコンノヾイル , インク リメンタルリンクの機能があるのて、 , 大き なプログラムて、も短時間て、コンパイル / リン クがて、きるようになっています。 デバッグが終わると , リリースパーショ ンて再度コンパイル / リンクを行い , 最終的 なプログラムを作成します。 新しい機能として , ソースプラウザが組 み込まれています。ソースプラウザは , ソー スプログラム上の関数 , 変数 , マクロ , 宣言 などの相互リファレンスの表示や検索する 機能てす。関数がどこて、定義されているか , どこて、使われているかを表示し , そこをマ ウスてクリックすれば , 関数が定義されて いるまたは使われているところを瞬時に見 ることもてきます。ソースプラウザは複数 のソースファイルに対して使えるのて、 , 大 きなプログラムの開発に便利だと思います。 コンバイラ オプジェクト指向を取り入れて C 十十にす る , もしくは独自の仕様て℃を大幅に拡張す るということは , MS-C Ver. 6.0 て、は行わ れていません。しかし ,ANSI C 規格準拠の 度合いが高められ , オプチマイズの強化 , インラインアセンプラのインプリメントな どにより Ver. 5.1 に対して大幅な変更が加え られています。 次頁の Tbl. 1 に MS ー C Ver. 6.0 て、追加さ れたコンパイラオプションの一覧を載せま したのて、 , 参照してください ANSI C 規格への準拠 Ver. 5.1 て、もかなり ANSI C に準拠してい ましたが , 今回のバージョンアップて、 , 通 常使用される範囲ては , ほば 100 パーセント ANSI C の仕様に準拠したのて、はないかと思 われます。 具体的な変更点を述べますと , キーワー ドとしては使えましたが , 実質的なコード が生成されなかった vo は t ⅱ e が正式にインプ リメントされました。ビットフィールドは 構造体て、しか使えませんて、したが , Ver. 6.0 ては共用体て、も使用て、きるようになってい ます oswitch 文て、 long および unsigned long が使えるようになりました。アドレス演算 子 & の仕様が ANSI と同じになりました。し たがって , 関数や配列に対して使用したと きに , 以前のように & を無視して直接ポイン タを得るようなことはしませんし , 得たポ インタは何へのポインタかを厳しくチェッ クします。 変数は ; 〃のように宣言することがて きましたが , ANSI の仕様に合わせて , "int a ; 〃のように必ず型かストレージクラスを 指定しなければなりません。過去のソース のことを考慮してか , 「エラー」にならずに 「警告」になります。 以上が ANSI C に準拠するための変更点て、 す。私が気づいた範囲て、の ANSI C との相違 占は , トリグラフシーケンスがインプリメ ントされていないことぐらいてす。 インラインアセンプラ C のソースプログラム上に直接アセンプラ コードが書けるようになりました。使用て、 きるコードは , MASM のサプセットになっ ています。 8086 および 8087 の命令を使うこ とがて、きます。コンパイルオプション / G2 を 指定したときには , 80286 および 80287 の命 令も使えます。 80386 , 80387 の命令は使え ません。そのほかの制限としては , データ ディレクテイプ (DB, DW, RECORD ・・ ) , マクロ , セグメントディレクティフ などが使えません。反対に , C のソースのシ ンポルや変数名 , 定数 , マクロなどが使え オプチマイズ グローバル最適化など , 全体的に最適化 の向上が図られているようてす。べンチマ ークテストをしたわけてはありませんが , 手元のいくっかのプログラムを使って MS- C Ver. 5.0 と比べてみると , ほとんど変わら ない場合もありますが , おおむね 5 パーセン ト ~ 15 パーセント速くなっているようて、す。 とくにラージモデルのほうがスモールモデ ルよりも効果が大きいようてす。 MS-C Ver. 5.1 て、はモジュール単位ての 最適化しかて、きなかったのて , 最適化に失 敗したときは , そのモジュールの最適化を あきらめるか , ソースプログラムをさらに 分割して再度最適化を試みるしかありませ んてした。 MS-C Ver. 6.0 ては , プラグマ を使って最適化をコントロールすることが て、きます。ポインタによる工イリアスて最 適化に危険な部分を制御てき , 高度な最適 化が可能てす。 関数呼び出しを速くするために , 通常の C の呼び出し規約とは異なる fastcall という 呼び出し規約が追加されました。 fastcall 規 速報 MS-C Ve 「 .6.0 緊急レポート 25
TbI.3 マクロおよひ丁 YPEDEF く assert.h > #define NDEBUG #define assert( ) #define BUFSIZ #define stdout #define INT MIN #define SIGFPE #define SIGILL #define SIGINT く er 「 0 「 . h > #define EDOM #defihe ERANGE #define FLT DIG #define FLT MAX 10 EXP #define DBL MIN 川 EXP #define LDBL MAX 10 EXP #define LC ALL #define LC MONETARY typedef ptrdiff t <limits. h> #define ULONG MAX #define LONG MIN #define LONG MAX #define UINT MAX #define INT MAX #define USHRT MAX #define SHRT MIN #define SHRT MAX #define CHAR MAX #define CHAR MIN #define UCHAR MAX #define SCHAR MAX #define SCHAR MIN #define CHAR BIT く locale. h> #define LC NUMER ℃ #define LC CTYPE #define LC COLLATE く setjmp. h> typedef jmp buf <signal.h> typedef Slg atomic く float. h> #define DBL MIN EXP #define DBL MIN #define DBL MAX EXP #define DBL MAX #define DBL MANT DIG #define DBL EPSILON #define DBL DIG #define FLT MIN 10 EXP #define FLT MIN EXP #define FLT MIN #define FLT MAX EXP #define FLT MAX #define FLT MANT DIG #define FLT EPSILON #define FLT ROUNDS #define FLT RADIX #define DBL MAX 10 EXP #define LDBL MIN 10 EXP #define LDBL MIN EXP #define LDBL MIN #define LDBL MAX EXP #define LDBL MAX #define LDBL MANT DIG #define LDBL EPSILON #define LDBL DIG #define LC TIME #define SIG IGN #define SIG DFL #define SIG ERR #define SIGTERM #define SIGSEGV #define SIGABRT '#define va end( ) #define va arg( ) #define va start( ) typedef va list く stdarg. h > く stddef. h> wchar Size t #define NULL く math. h> #define UNDERFLOW #define OVERFLOW #define DOMAIN #define ERANGE #define HUGE VAL #define PLOSS #define TLOSS #define SING #define EDOM ロ ()P SEG, FP OFF など ) が定義されてい ます。 く fcntl.h> ファイル操作 ( ストリームて、はない ) に関 連する情報が定義されています。 く iO. h > ファイル操作 , および低水準入出力に関 する関数が宣言されています。 く m 引 loc. h > メモリの割り当て , 解放 , 報告に関する 関数宣言 , ヒープ管理に関するマクロ , 構 造体などの定義が行われています。 く memory. h> メモリ操作関数 ( mem て、始まる ) が宣言さ 19 6 れています。通常 , このヘッダは < st 「 ing. h > 44 CMAGAZINE によって自動的にインクルードされるよう になっています。 く process. h > 使用される補助的なヘッダが置かれます。 リ SYS 〃の下には , 上位のヘッダによって ヘッダディレクトリ内のサプディレクト く sys*???. h> ています。 サーチ , ソートに関する関数が宣言され く serch. h > ステム ) に依存したものとなっています。 れる処理は , 実行環境 ( オペレーティングシ います。当然 , これらの関数によって行わ セスの制御を行うための関数が宣言されて プログラム自身 , およびチャイルドプロ <stdio. h> #define stdin #define stderr #define EOF #define FILE #define #define #define typedef fpos t #define TMP MAX #define SEEK SET #define SEEK END #define SEEK CUR #define FILENAME MAX #define FOPEN MAX IONBF IOLBF IOFBF <stdlib. h> #define #define #define typedef div t MB CUR MAX RAND MAX EXIT SUCCESS #define EXIT FAILURE ldiv t <sys%utime. h> く sys*types. h > <sys%timeb. h> <sys*stat.h > <sys*locking. h> TbI. 4 sys ¥の下に置かれる補助的なヘッダファイル れているファイルは , プリプロセッサを作 が収められています。ただし , 今回供給さ げた標準ヘッダと準標準ヘッダのファイル 本号の付録ディスクには , ここて、取り上 かれます。 て、 , 通常 , TbI. 4 に示す 5 個のファイルが置 これは , UNIX における慣習に従ったもの #define CLOCKS PER SEC struct tm time t typedef clock t く time.h>