環境 - みる会図書館


検索対象: 月刊 C MAGAZINE 1990年10月号
60件見つかりました。

1. 月刊 C MAGAZINE 1990年10月号

Turbo C 十十徹底チェック② Turbo C 十十の開発環境 滝尾進 和「 bo シリーズは , これまでもユーサフレンドリ な開発環境か高く評価されていた。 Turbo C 十十 では , この統合開発環境 (IDE ) がさらに拡充され た。本セクションでは , 和「 bo C 十十 Ver. 1.0 の 開発環境にスポットをあててみていきたい。 マウスによるウインドウの操作としては , と呼ばれ , 従来の Turbo C などの統合開発 アクテイプウインドウの選択 , ウインドウ 環境と比べ , 大輻に強化されている。最大 はじめに の移動 , リサイズ , ズーム , クローズ , ウ の強化点はマウスオペレーションによるオ インドウのスクロールなどがある。 ーバラッヒ。ングマルチウインドウをサポー ダイアログボックス ( Fig. 2 参照 ) は , 置換 米国 Borland 社の Turbo C 十十は AT&T トしたことて、ある。オーバラッヒ。ングマル メニューの「検索文字列」「置換文字列」「検索 の C 十十 ( 以下 C 十十 ) Ver. 2.0 に準拠し チウインドウは Turbo Debugger(Ver. 1.0 ) 方向」などのように , 複数の項目を設定する た C 十十コンパイラて、ある。 Turb0C 十十 て、すて、に採用されていたが , TurboC 十十 場合に用いられる。ダイアログボックスて、 の特長は , ①オプジェクトファイルを直接 て、はさらにウインドウやメニューをマウス は現在設定されている値を確認しながら入 生成するネイテイプコンパイラて、あること て、操作て、きるようになった ( Turbo Debugger 力が行えるのて、 , 入力方法をまちがえるよ と , ②従来の Turbo シリーズと同様に強力な て、も Ver. 2.0 からはマウスをサポートして うな失敗はまず起こらないだろう。 統合環境をもっことて、ある。 いる ) 。 本稿は , IBM 社 PS / 55 モデル 5530 を用いて IDE は , テキストウインドウ , ダイアログ ルチファイル ポックスの 2 種類のウインドウをもち , 操作 Turbo C 十十を試用したレポートて、ある。 テイタ 性 , 応答性も良好て、 , 非常に使いやすい やたらと分厚い英文のマニュアルと使い馴 テキストウインドウ (Fig. 1 参照 ) はソース れない IBM マシンを用いてのレポートなの Turbo C 十十のエデイタは , マルチファ プログラム ( 工デイタ ) や , ウォッチ , コン て、思い違いやまちがえた記述があるかもし パイルエラーなどのメッセージを表示する。 イル / マルチウインドウ方式を採用してい れないが , その点はご了承願いたい Turbo C て、も , これらをマルチウインドウ る。読み込めるファイル数の上限はメモリ て、表示することがて、きたが , ウインドウの 容量にのみ依存し , 特別な制限はないよう 合開発環境 (I DE) 位置や大きさなどを自由に変えることはて、 だ。 きなかった。 Turbo C 十十て、は , これらを ファイルを読み込むとスクリーンにウィ マウスやキーボ、一ドを用いて自由に変える ンドウが開き ( Fig. 3 参照 ) , 編集が可能にな Turbo C 十十の統合開発環境は IDE る。 MIFES などのエデイタと異なり ,Turbo ことがて、きる。 (lntegrated Development Environment) 70 CMAGAZINE 1990 10

2. 月刊 C MAGAZINE 1990年10月号

Behind Me, LiSt #include く stdio. h> 48 : } Get Thee く errno. h 〉 く string. h> syscalls. h" 5POW0 0f UNIX! クローズされるようにて、きます。 し , exec がコールされるときに , 自動的に スクリプタの close - on - exec フラグをセット ステムコール fcntl を使って , ファイルディ される前にクローズしておくべきて、す。シ 要なファイルは , 新たなプログラムが実行 を設定するためには便利て、す。しかし不必 ムの標準入力 , 標準出力および標準ェラー はオープンのままて、す。これは , プログラ 1 : 3 : 5 : 6 : 7 : 8 : 10 : 12 : 13 : 14 : 15 : 17 : 20 : 22 : 23 : 24 : 25 : 26 : 28 : 29 : 30 : 31 : 32 : 33 : 34 : 35 : 36 : 37 : 38 : 39 : 40 : 42 : 43 : 44 : 45 : 46 : 47 : #include 2 : #include く stdlib. h> 4 : # i nc 1 ude #include char *cmdtok(char (s) : 9 : / * execs : ファイル ( 文字列パラメータ ) を実行 * / int execs(const char *cmdl in) char *tcmdl in = NULL; int argc ニ NULL; Char **argv char *p ニ NULL; / * コマンド行の作業用コヒ。ーを作る * / / * コマンド行用 * / / * 引数カウント * / / * 引数配列 * / / * 作業用の char ポインタ * / (char *)calloc ((size-t) (strlen (cmdlin) + 1), sizeof(*tcmdl (n) ) : tcmdlin strcpy(tcmdlin, cmdl (n) ; / * コマンド行から argv の配列を構築する * / argc ニ NULL; argv = cmdtok(tcmdlin) : P while ( 1 ) { / * 新たな argv 成分用にメモリをアロケートする * / (char * * ) real loc(argv, (size-t) ((argc + argv = NU しい { argvCargc] = NUL し : free(argv[argc]) : while (--argc > ニ 0 ) { / * メモリを開放 * / execv(argv[0], argv) : / * プログラムを実行する * / P = cmdt0k()U しし ) : strcpy(argv[argc 十十 ] , p) ; sizeof (*argv[argc])) : argv[argc] break; I) * sizeof(*argv))); (char *)calloc((size-t)(strlen(p) + 1 ) , free(argv) : free(tcmdlin) : return ー 1 : execl("-"/bin/sh' cmdlin, NULL); ルが fo 「 k をコールして , 新たなプロセスを作 て , 引数の配列を構築します。新たなシェ sh は cmdlin の中のメタキャラクタを展開し がコマンド行を実行する方法と同じて、す。 す。これは ,ANSI C のライプラリ関数 system を実行して終了するよう , sh に指示しま - c は , 次の引数 ( cmd ⅱ n ) の中のコマンド行 この方法の利点は , コマンド行の処理中に シェルの機能を使えることて、す ( もちろん , 必要に応じて execs のメタキャラクタの種類 を増やすこともて、きます ) 。ひとつの欠点 は , 余計なプロセスが生成されることて、す。 それに , もとのプロセスは新たなシェルの PID を知っていますが , そのコマンドを実際 に実行しているプロセスの PID は知らないの て、す。 exec 関数がコールされるとき , ファイル C のプログラムは , そのエントリポイント て、ある関数 main の第 2 引数を介して , 自分の 引数リストにアクセスて、きます。 intmain ( int argc, char * argvC ] ) て、 , argc は argv の 成分の個数にセットされます ( 最後の NULL を除き ) 。慣行的に , argv はプログラム 名 (execlp と execvp の file 引数 ) て、す。これは exec が要請していることて、はありません が , 実行されるプログラムがしばしば必要 とします ( a 「 gv [ O ] がプログラム名て、あるこ とを ) 。 環境へは , グローバルなポインタ extern char * * envi 「 on を使ってアクセスて、きま す。 UNIXC の実現系の多くが , exec に渡 す環境として , main が第 3 の引数 char * envp [ ] をもてるようにしています。ただ し , これは ANSI C 規格からの逸脱なのて、 , 環境へは envi 「 on を使ってアクセスしたほう が , プログラムの可搬性は大きくなります。 それに , en ⅵ「 on は実際の環境へのポインタ て、すが , envp はプログラムの実行開始時 の , 環境のコヒ。ーへのポインタて、あるにす ぎません。ライプラリ関数 putenv を使って 環境を変更すると , 環境の所在が変わり , envp のアドレスが無効になることもありえ ます。 セスの終了 プロセスはシステムコール , voidexit(int status ) を使って終了させます。 status は終了 するプロセスの親に報告される値てす。 status の値に ( 親と子が一貫した解釈をするかぎり り , 40 その引数配列て、 exec をコールします。 CMAGAZINE 19 10

3. 月刊 C MAGAZINE 1990年10月号

特集 0 十十とオプジェクト指向 TabIe 1 C 十十処理系の比較 C 十十処理系 形式 対応する C 十十のバージョン グラフィックスライプラリ その他の特徴 えるて、しよう。 Turbo C 十十 ネイテイプコンノヾイラ 2 .0 あり 統合開発環境をもつ オーノヾレイ IDEA C 十十 インタブリタ 1 .2 ( 旧 M ー PC ) あり 統合開発環境をもつ Zortech C 十十 ネイテイプコンバイラ 1 .0 ( PC ー 9801 ) なし 独自のオプジェクト形式 Miwa C 十十 トランスレータ なし MS-C または Turbo C が必要 MS ー DOS 上て、動作するおもな C 十十処理 系を比較した一覧表 ( Table 1 ) を作成しまし クラスライプラリ たのて、 , 参考にしてください。 クラスライプラリ TabIe 2 Turbo C 十十の標準クラスライプラリ このクラスライプラリは , それぞれにヘ 1 参照 ) 。 をルートにして階層構造になっています ( Fig. を除いて , 抽象クラス ( 後述 ) て、ある Object プラリは , 非常に豊富て、す。これは , 一部 Turbo C 十十 Ver. 1.0 独自のクラスライ まとめました。 覧表と関連するヘッダファイルを Table 2 に のソースコードも付属しています。その一 イルとして提供されており , 当然ながらそ ます。 AT & T 互換のクラスは , ヘッダファ と独自のクラスのライプラリが付属してい TurboC 十十には , AT & T 互換のクラス 複素数型 BCD 型 ファイルストリーム型 ストリーム型 ッダファイルとソースファイルが提供され ています。また , すて、にコンパイルされた オプジェクトのライプラリ ( スモールメモリ モデルのみ ) も , 提供されています。このク ラスライプラリの説明は , フロッピーディ スク上のドキュメントファイルに収められ ー = マニュアル ています。 TurboC 十十のマニュアルは , 以下の 4 冊 のて、す。 ュアルも非常によくて、きた , すばらしいも したが , この Turbo C 十十 Ver. 1.0 のマニ Turbo C Ver. 2.0 のマニュアルもそうて、 て、構成されています。 ① ② ③ Getting Started Useds Guide Programmeds Guide ヘッダファイル iostream. h stream fstream. h bcd. h complex. h . h ④ Library Reference ①の、、 Getting Started" は , 入門書て、 す。インストールの方法の説明から始まっ て , 統合開発環境の入門 , C, C 十十の入 門 , 統合開発環境てのデバッグ手法と続い ていきます。 この中て、 , 章番号て、いうと , 5 章と 6 章が C 十十についての入門的な解説になっていま す。この解説はていねいに書かれており , プログラムの実例も豊富に盛り込まれてい ます。また , このプログラム例は , フロッ ヒ。ーディスクに収録されており , プログラ ムの動作を実際に実行して確かめながら , テキストを読み進むことがてきます。 ②の、、 User's Guide" は , 統合開発環境 の使い方 , およびコマンドラインコンパイ ラ , ユーティリティの説明書て、す。 ③の、、 Programmer's Guide" は , Turb0 こて、は , C 十十の言語仕様の解説書て、す。 BNF 記法を用いて言語の文法を規定してい ます。また , 言語のセマンティクス ( 意味 ) についてもくわしく記述されています。 そのほか , ランタイムライプラリ , C 十十 のストリーム , クロスリファレンス , メモ リモデル , 浮動小数点演算 , オーバレイ , ビデオ ( グラフィックス ) 関数 , アセンプラ とのインタフェイス , 工ラーメッセージな どの情報も載録されています。 ④の "Library Reference" は , ライプラ 特集 C 十十とオプジェクト指向 77

4. 月刊 C MAGAZINE 1990年10月号

イルポインタやアクセスモードを変えるこ とにより , 互いに干渉し合うことがて、きま す。 第 2 の注意点が , ファイルアクセスがノヾッ ファリングされる場合・・・・・・ C 言語の stdio のラ イプラリを使用する場合・・・・・・に関して存在 します。 stdio を使ってデータをファイル に書き込むとき , データはバッフアが満杯 になるまて、 , またはバッフアをフラッシュ する関数がコールされるまて、 , あるいはフ めた一般名て、す。 exec 関数の原型は execve としての , プログラム名とそれに渡す引数 ァイルがクローズされるまて、 , メモリ上に て、 , これは int execve(char *path, char * を必要とします。しかしこのデータをユー argv [ ] , char *envp [ ] ) ; という引数形 バッファリングされます。このときはシス ザ入力やファイルから取得するときは , そ 式て、コールされます。 path は実行するプロ れは通常は単一の文字列て、あり , したがっ テムコールの w 「 ite 力すコールされて , ノヾッフ アの内容をファイルに書き出します。しか グラムのパス名 ( ファイル名の前に所在ディ て配列またはリストへとトークン化されな し , バッフアはプロセスの一部なのて、 , プ レクトリ名などのパス名をつけたもの ) て ければなりません。 List 4 に , execs 関数と ロセスの複製時にはそれも複製されていま す。 argv ( 引数の配列 ) は , この新たなプロ いう新しい exec 関数を示しますが , これは コマンドを文字列形式て、受け取るものて、す。 す。 fo 「 k がコールされたときに , バッフア内 グラムに渡す引数の文字列の配列て、す。 envp に書き込み用データがあると , このことに ( 環境ポインタ ) は , name=value という形 execs 関数の環境版 execse と , パス名版 よって予期せざる結果が生ずることがあり 式の文字列の配列て、す ( 例 : TERM = execsp は , 次のようになるて、しよう。 VTIO の。環境には通常 , ユーザのホームデ ます。 int execs(cha 「 *cmdlin) ; / * 原型 * / List 2 て、は , もとのプロセスが fputs をコ ィレクトリ , 端末のタイプなどの情報が入 ールして , 1 行のテキストをファイルに書き っています。 argv と envp はともに , NULL int execse(char *cmdlin, char *envp [ ] ) ; 込んて、います。 fo 「 k をコールした後て、 , 子と ポインタて、終わっていなければなりません。 / * 環境版 * / 親の両方がファイルをクローズして , 両方 exec システムコールのそのほかの 5 つのタ のプロセスのバッフアの中身をフラッシュ イプは , 基本的には execve と同じて、すが , int execsp(char *cmdlin) ; / * パス名版 * / しています。その結果 , データはファイル 引数の形式がやや違います。 List 3 が , その execs 関数は文字列 cmdlin をトークン化し 完全な一覧表て、す。これらの関数は , 引数 に二度書き込まれます。 て引数の配列を作り , それを使って execv 関 を a 「 gv て、渡すか , argO, argl , argn, プセスの変容 数のどれかをコールします。トークン化は , NULL というリストて、渡すかという 2 グルー cmdtok 関数をコールして行います ( ソース プにわかれます。関数名はそれを反映して をお見せしていません ) 。 cmdtok 関数は , 一般的にプロセスは , 新たなプログラム いて , v がっくのが配列 (vector) 渡しの関 ANSIC の st 「 tok 関数と似ていますが , トー 数 , ーがっくのがリスト渡しの関数て、す。 を実行するために生成されます。システム クン間の連続するホワイトスペースを 1 個の コール exec は , 新たなプログラムを起動し p て、終わる関数は , ファイル名を引数に取 および て , それを exec へのコールを実行したプロ スペースとして扱い , \ , ります。ほかはパス名を必要とします。 p て、 、、 # 〃というメタキャラクタを認識します。 グラムと置換します。その新たなプログラ 終わる関数は , コール側プロセスの環境内 これらのメタキャラクタの機能は , シェル に定義されているパス ( たとえはア ATH = : / ムは , 最初から実行されます。コールした の場合と同じて、す [ 参考文献 1 ] 。 bin:/usr/bin のようなパス ) を探索して , プログラムが新たなプログラムて、置換され execs 関数を使う代わりに , 既存の exec 関 るのて , exec のコールは成功するとリター ファイルを見つけます。 ンしません。通常は ( ただし必ずて、はなく ) , e て、終わる関数は , 新たな環境を渡せま 数のどれかて、シェルを起動して , それにト ークン化をさせることもてきます。実行さ fork コールの直後に exec がコールされま す。ほかは , 現在の環境を新たなプログラ れるコマンド行の入っている文字列が , シ ムへコヒ。ーします。 す。 exec 関数は , 6 つのシステムコールをまと 6 つの exec 関数はすべて , 個々のトークン ェルへの引数として渡されます。 List int execl (path, argO, argl, 1 : int execle(path, argO, argl, 2 : int execlp(file, 3 : argO, argl, 4 : int execv(path, argv) 5 : int execve(path, argv, envp) 6 : int execvp(file, argv) char *path, *file, *argn, *argv ロ , *envp[] : NU しし ) argn, NUL し envp) argn, NULL) argn, UN Ⅸの spawn よ , われを助けたまえ / 39

5. 月刊 C MAGAZINE 1990年10月号

setjmp は呼び出されたときの環境をパラ メータ env に格納し , 必ず 0 を返します。 env に格納された環境は後て longjmp が回復しま す。 longjmp は , int longjmp(jmp buf env, int val) : と宣言されています。 setjm P によって格納 された環境 env を回復することによって大域 脱出します。その結果 , env をセットした setjmp の呼び出しの直後に制御が移りま す。つまり , あたかも setjmp からリターン してきたように見えます。 ことは , setjmp の直後て、は , 本当 に setjmp からリターンしてきたのか , longjmp によって大域脱出したのかがわからなくな るのて、はないかと思うかもしれませんが , そこはそれ , よく考えられています。 longjmp から制御が移ってきたときには , setj m p は longjmp のパラメータの val の値を返しま す。このメカニズムによって , どちらから 戻ってきたのかを判定て、きるのて、す。 おや , longjmp(env, O) としたときには マズイんじゃないか ? と思ったあなた , あなたはスルドイ / しかし大丈夫て、す。 ANSI 規格て、は , val に 0 を与えたときには longjmp(env, 1 ) となる , と規定されていま 25 : } List 3 setjmp/longjmp の例 1 : 2 : 3 : 4 : 5 : 7 : 8 : 9 : 1 2 : 14 : 17 : 22 : 23 : 24 : #include く setjmp. h> JIIIP- int i nt int buf env; f3() i f ( ェラーを検出した ) return (ERROR) : } se { if (setjmp(env) fl() f2() longjmp(env, 1 ) ; / * setjmp か longjmp に す。 setjmp/longjmp のノヾラメータてある jmp buf 型て、すが , これは実際には CPU の環境を 保存するのに十分な大きさをもつ配列を typedef したものて、す。配列て、すから setjmp (env) という呼び出して、うまく動作します。 setjmp には env の先頭アドレスが渡されます から , env の内容を正しく書き換えることが て、きるわけて、す。 ところて、 , jmp ー buf が配列て、はなくて構造 体として定義されていたとするとどうなる て、しようか ? あ , この話は , きだあきらさ んが書いてくださるそうなのて、「 ANSIC more 」を読んて、ください List 2 を setjmp/longjmp を使って書き換 えると List 3 になります。すっきりしたと思 いませんか ? 使用上の注意 まうばかりか , いとも簡単に暴走してしま とまったく動かないプログラムになってし setjmp/longjmp なのて、すが , 使い方を誤る 例外処理にはけっこう便利に使える ' よる大域脱出 * / らのリターン * / こて、は setjmp/longjmp を使ううえて、の注意 います。そんなことにならないように 点をいくっか挙げておきます。 まず確実に setjmp することて、す。 setjmp していない env をノヾラメータにして longjmp を実行すると ; その結果は不定て、す。何が 起こるかわかりません。おそらく暴走する ことになるて、しよう。 longjmp は env が正しく設定されているか どうかといった正当性のチェックはしませ ん。強引に env に格納されているものを CPU の環境に設定してしまいます。 env が正しく 初期化されていないのに longj mp をすると , プログラムカウンタやレジスタ群にゴミの 値を代入することになります。プログラム カウンタにゴミの値が入るということは , どこかとんて、もないところにジャンプする ということて、すから , その後の正常な動作 を期待て、きるはずがありません。 setjmp した関数が終了してか引 ongjmp し てはいけません。これも暴走などの悲惨な 目にあいます。 関数が実行されるとき , スタックには上 述したリターンアドレスのほかにローカル 変数のためのエリアやワークエリアが確保 されます。このエリアをアクティベーショ ンレコード ( 活動記録 ) と呼びます。アクテ ィベーションレコードは新たに関数が呼び 出されるたびにスタック上に作成され , 関 数が終了するたびにスタックから取り去ら れます。 setjmp が env に格納するデータの中には , setjmp を呼び出した関数のアクティベーシ ョンレコードのアドレス ( つまりスタックポ インタの値 ) が含まれています。 longjmp は スタックポインタの値をこのアドレスにし ますから , long p を実行する時点て、ターゲ ットになるアクティベーションレコードは スタック上に存在していなければなりませ ん。 setjmp した関数がすて、に終了している場 合 , ターゲットのアクティベーションレコ ードはもはや存在していません。そこはフ リーエリアになっているか , あるいは別の 関数のアクティベーションレコードの一部 になっているて、しよう。こういう状況て、 longj 128 CMAGAZINE 19 10

6. 月刊 C MAGAZINE 1990年10月号

特集 0 十十とオプジェクト指向 ・従来とは異なるインテリジェントなオ ーバレイマネージャ ( VROOMM ) ・マウスやマルチウインドウが使用可能 な新しい統合環境 (IDE ) 以ド , それそ。れ簡単に説明していこう。 ANS C と C 十十を包含 Turbo C 十十 Ver. 1.0 は , AN S I C と AT&T C 十十 Ver. 2.0 というふたつの処 理系の機能を合わせもっている。 C 十十は 一般的に C 言語プログラムのコンパイルが可 能だが , ここて、いう ANSI C の処理系の機 能というのは , たんに , A N S I C て、書かれ たソースもコンパイルて、きるということて、 はない。 A N S I C のモードて、コンパイラを 動かしたときは , AN S I C の許すソースし かコンパイルて、きない , つまり C 十十のプ ログラムはコンパイルて、きないということ て、ある。これにより , 普通の C のプログラ ムも安全に開発て、きるわけて、ある。 ソースファイルが , A N S I C のものか , C 十十のものかは , ファイルの拡張子て、判 断される。 A N S I C の場合は、、 . c 〃 , C 十十 の場合は、、 . cpp 〃という拡張子をつけてお くと ,Turbo C 十十の処理系が勝手に判断 してくれる。 オーノヾレイマネージャ (VROOMM) Turbo C 十十 Ver. 1.0 のオーバレイマネ ージャは V R O O M M(Virtual Runtime Object-Oriented Memory Manager) と呼 ばれ , 従来のオーバレイマネージャよりも 洗練されたものになっている。 今まて、あったオーバレイマネージャは , オーバレイエリアにはひとつのモジュール しか置けなかったり , 複数置けるものて、も , モジュールの置き方はモジュール間に階層 的な構造を定義するなどしてプログラマが 指定する必要があった。プログラムをオー TabIe 1 項目 マシン CPU メモリ HDD テスト環境 環 境 SONY Quarter L(PCX-300) 386SX(16MHz) IM ノヾイト ( EMS , XMS はなし ) 内蔵 40M バイト バーレイするモジュールに分ける作業は , プログラムの実行速度を落とさないように 制御の流れを考えて慎重に行う必要があり , なかなか難しかった。 V R O O MM て、は , そういったオーバレイ モジュールの構成に気をつかう必要はない とにかく細かめにオーバレイモジュールを 作っておけば , あとは実行時にマネージャ がうまくやってくれる。 オーバレイモジュールが置かれる領域 ( V R O O MM て、はオーバレイバッフアと呼ん て、いる ) には , 実行時に , 置けるだけのモジ ュールが置かれる。新たにひとつモジュー ルをロードしてくる場合て、も , すて、にある モジュールが必す追い出されるわけて、はな い。空き領域があれば , すて、にあるモジュ ールはそのままにして , 新しいモジュール をロードしてくる。領域がない場合は , そ TabIe 2 べンチマークー覧 分類 浮動小数点演算の速度を測る もの ライフラリの速度を測るもの 自体の速度を測るもの コン八イラが生成するコード プログラム whet. c SP に 0. C getchar. C ー OWiO. C printf. c Str. C m 訓öC. c dhry. c Sleve. C maze. C m ystr. C int. C の時点て、使われていないモジュールから追 い出して空き領域を作り , それをロードす る。この手法をダイナミックスワッヒ。ング と呼んて、いるが , これはまさに仮想記憶て、 ある。オーバレイバッフアのサイズはユー ザが指定て、きて , 当然大きく取ればプログ ラムのパフォーマンスは向上する。 V R O O MM は E M S や X M S にも対応 していて , 追い出すモジュールを E M S / X M S に待避し , 再度必要になったときに ディスクて、はなく E M S / X M S からロード することがて、きるようになっている。あた りまえのことて、あるが , ディスクからロー ドするよりはるかに速い Turbo C 十十 Ver. 1.0 自身も V R O O MM を使っており , 統合環境て、コンパイル を行うときに使えるメモリ容量が , 以前よ り 100K バイトぐらい広がっている。 E M S / XM S にも対応しており , それらをスワッ プエリアにすれば統合環境のレスポンスを 速めることがて、きる。 新しい統合環境 (IDE ) Turbo C 十十 Ver. 1.0 の統合環境には , 新たに I D E (lntegrated Development Environment) という名前がつけられた。新た プログラムの内容 ウェットストーン ( 浮動小数点演算の速度 ) 数学関数のテスト ( おもに三角関数 ) getchar/putchar テスト read/write テスト scanf/printf テスト ストリング関数テスト m 訓 OC / f 「 ee 関数テスト ドライストーン ( 総合的なコードの速度 ) 工ラトステネスのふるい 迷路作成プログラム str. c のストリング関数を自分で作った場合 冗長な整数演算 特集 C 十十とオプジェクト指向 65

7. 月刊 C MAGAZINE 1990年10月号

: 龜新 MS - DOS プロクラミング入門 そこて、本連載ては MS ー DOS の機能のなか 場合には筆者が使用経験し , ある程度の資 などを考慮したものといたします ( ただし , からおもしろそうなテーマをひとつずっ取 料も入手している 動作確認は PC ー 9801 シリーズのみ ) 。 り上げその原理を説明し , アセンプラや C PC ー 9801 シリーズ て、きるだけ多くのコンパイラに対応させ J ー 3100 シリーズ 言語による簡単なプログラミング例を示し たいのて、すが , ヘッダファイルやライプラ ていくことにしました。解説を希望する機 AX マシン リ関数に違いがあるためなかなか難しい面 能がありましたら , 本稿への手厳しい批判 TabIe 1 MS-DOS の構成 を添えて編集部宛てにお便りをください 機能 ファイル名 とりあえず連載を開始するにあたって ドライプ A : , B ・ テパイスドライバ ( CON , AUX, CLOCK, 9. SYS 1 リダイレクト MSDOS. SYS システムファンクション INT 20h ~ 3Fh 2 ファイルの日付 / 属性の取得と変更 COMMAND.COM 内部コマンド ( COPY , TYPE, DEL, ・・・ ) , バッチファイルの起動 3 ファイルの検索 標準出力に出力するプログラム ( testout. c) 4 デバイスドライバとの会話 というような項目を拾い上げてみましたが 1 : #include く stdio. h> ( もうひとつパッとしないてすね ) , 今後の 2 : 3 : int main(void); 反響により内容は変わっていくと思います 4 : 5 : int main() し , 任期を満了しなくてもネタ切れと同時 printf( " 標準出力 \ n " ) : 7 : に本連載もヾ無事〃終了してしまうてしょ return( 0 ) : 8 : う ( 連載止めるにや刃物は要らぬ / 批判の 3 つも書けばよい ! ? ) 。 前提となる MS-DOS の環境 本稿を書くうえて想定している M S ー D O S の環境としては , MS-DOS Version 3. x Microsoft C Version 5.10 Microsoft Macro Assembler Version 5 . 10 を標準の環境とし , とくに断わらない場八 はこの環境を前提にしています。動作確認 は PC ー 9801 シリーズの MS-DOS 3.3B ( 1989 ー 11 ー 27 ) て行いますが , てきるだけマシン依 存を避けたプログラミングをこころがけま す。したがって MS-DOS 3.1 以降が動作す るマシンて、あれば問題なく動作するはずて す。ただし , PC ー 9801 シリーズの MS-DOS 3.1 て、もバージョンにより一部動作の異なる 部分がありますから , ほかのマシンの MS- DOS< も動作が異なる場合があるかもしれ ません。手元にマシンがあれば確認するの てすが , 一介のエンジニアに各種のマシン がそろえられるはずがありません。その点 もし , マシンに依存す はご容赦ください List 出力のリダイレクトテストプログラム 1 (testl . c) 1 : # i ncl ude く std i 0. h > 2 : #include く process. h> 3 : 4 : int main(void); 5 : 6 : char *cmd[] "testout ” 7 : 8 : NU しし } : 9 : int main() return( spawnvp( P-WAIT, cmd[ 0 ] , cmd ) List 出力のリダイレクトテストプログラム 2 (test2. c) List 1 : #include く stdio. h> 2 : #include く process. h> 3 : 4 : int main(void); 5 : 6 : char *cmd ロ 7 : command ” 8 : 9 : ” testout ” NUL し } : 13 : int main() return( spawnvp( P-WAIT, cmd[ 0 ] , cmd ) 新 MS-DOS プログラミング入門 93

8. 月刊 C MAGAZINE 1990年10月号

「 ) E ハ + ャ 1 2 オフジェクト指向言語 C + + 統合開発環境 —IDEA C + + が操作性、デバッグ機能をさらに強化してパワーアップしました一 学習用として最適なインタブリタ方式を採用し強力なビジュアル・デパッガを搭載。 IDEA C + + は C / C + + 言語の入門 ~ プログラム開発用の統合環境です。 能や、 # include 文を判別するタグジャンプなど ) グによるシス をサポートするプログラム開発用工テイタです。ま テムのクラッ たテキストの シュを未然に C の学習から C 十十による開発ま 編集、検索文 防ぐこ勧、 で・“ 字列入力等 できます。 の編集、テパ IDEA C++ ( イテアシープラスプラス ) は高機能 また、 C や ッガなどの操 C 十十で最も フルスクリーンエテイタ、ソースレベルテパッガを ーテッ、ツガー 作方法はボッ 厄介で発見 u こ 備えた統合化 C 十 + インタープ丿タです。 カップメニ くい、不正なポインタによるバグを自動的に発見す M 旧 ES ライクな高性能工テイタ、ポップアップメ ースクリーンエデイター ュー / ウイン ニュー、日本語によるエラーメッセージ、インタブ丿 るこ勸、できます。 ドウを中心にシンプルに統一されていますので、極 タによる安全なプログラミング環境など、入門者の めて容易にマスターできます。 方にもすぐこ使っていただけます。また強力なテパ ッガを内蔵していますので本格的な開発ツールと して利用することもできます。 IDEA C は C 言語のインタープリタとしても 利用できますので、 C 言語の学習から C 十十言語に よる開発まで オールラウン N こ活用でき る C/C 十十 統合環境です。 •IDEA C 十十 version 1. * を御購入 済みのユーザー様へ IDEA C 十十 verl .2 への無償パージョンアップを行 っております。ユーサー登録カードをまだご返送いた だいていない方は早急にご返送下さい。ユーサー登 録が済み次第、 ve 「 5i0n1 2 をお送り致します ■学校・法人向けサイトライセンス 教育教材として複数の旧 EAC 十十をご使用になる場 合などのために、特別価格のサイトライセンスがござ います。お問い合わせ下さい。 ESONY NEWS バージョン開発中 NEWS(Xwindow)'<—ジョン 1 991 年初頭発売予 定。そのほかの IJN Ⅸ EWS にも移植中です お問い合わせ下さい。 オプジェクト指向テパックツール ■プロフェッショナル向け旧 EA C 十十 EX ・・インスペクタ ライプラリを自由に拡張できる本格的な開発用の IDEA C 十十パッケージです 1 78 , 000 円 ( 好評発売中 ) 大規模なプログラム開発か可能 IDEA C 廾のテパッガか提供するインスペクタ ・・・オプジェクトスワップ機能 機能は、 class 、 st 「 uct 、 union 型などの変数 をテータタイプに合わせた形式で表示 / 変更する 旧 EA C + + は、テキストテータや、テパッグ用の ー DEAC 十十の主な特徴 シンボルテープル等の作業用テータをテンボラリ ことができます。また class 型変数ではテータ C 十十インターフリタ / ソースレベルデバッガ ファイルに自動的にスワップする事でメモリを効率 以外にメンバ関数などの情報を表示することもで ・中間言語形式のインタープリタ ( C 十十のソースファ 的に使用します。このため、日本語 FP 等のテパイ きます。関数の情報をインスペクトするとその関 イルを中間言語にコンパイル / リンクし、翻訳実行 ) ・ 複数のソースファイルによるプログラムや大規模なプ スドライバを組み込んだ状態でも大規模なプログ 数か定義されたソースファイル名 / 行番号を表示し、 ログラム ( 1 0 , 000 ステッオ呈度 ) の開発が可能・マ その位置にタグジャンプすることもできます。 ラム開発か可能です。 イクロソフト C コンパイラに準拠した約 300 の関数 ( 日 本語処理関数 / グラフィック関数を含む ) 、 C 十十の標 準ライプラリ (stream 、 complex 、 vector ) をサポー ト・日本語によるコンパイルエラー / 警告の表示・コ ンパイルエラーの発生した位置にカーソルを移動させ る、タグジャンプ機能・必要なファイルだけを自動的 にコンパイル / リンクする自動 MAKE 機能・オンメモリ による高速なコンパイル / リンク ( 約 6000 行 / 分 ) ・ 古い C ( K & R 、 ANSI 準拠 ) のインターオ丿タとして使用 可能・ M ー WAC 十十トランスレータ、マイクロソフト C コ ンパイラに対応・ C 十十のソースレベルでのデパッグ が可能・変数の値を対話的に参照 / 変更できるデー タインスペクタ機能・トレース、ステップ実行機能。 最大 16 簡所設定できるプレイクポイント・最大 10 個設定できる変数ウオンチ機能・不正なメモリアクセ ス等を未然に検出する実行時工ラーチェック機能と、 工ラーを起こした位置へカーソルを移動させるタグジャ ンプ機能 スクリーンエデイタ ・最大 120 個のファイルを編集可能なマルチファイ ル・同時に 2 つのファイルをオープンできるデュアル ウインドウ方式・ポップアップ・メニューと、 2 ストロー ク・キー入力の両方式サポート・クラスや関数などの 情報を対話式に調べることができるプラウサ機能・ 行、文字列、箱型のカット & べースト・各カットパッファ ま要コンバイラとの互換性確保 のポッフンツブウインドウによる編集、プ ) ント出力機能 ・異なるファイル間移動もできるタグジャンプ機能・ キー割付のカスタマイズ可能・ ATOK 等の各種日 IDEA C 廾で開発 ( テパッグ ) したソースコード 本語 FP 対応 統一された擽作性 安全なプログラム環境 は市販の C 十十トランスレータや C 十十 / C ネイテ ・・・高機能工テイタ・統合環境 ・・・実行時工ラーチェック機能 イプコンバイラを用いて EXE ファイルに変換でき 71DEA C + + 1.2 ます。また C 言語の標準ライプラリやグラフィック 対応機種 : NEC PC -9801 シリーズ IDEA C + + のエテイタは、 M 旧 ES ライクな機能 IDEA C 廾のテパッガはステップ実行やプレイ EPSON PC -286 シリーズ 関数はマイクロソフト社製 C コンバイラと互換性か ( マルチファイル / テュアルウインドウ、文字 / 行 / 箱 クポイント、変数ウォッチ機能などの他に、インター 動作環境 : MS - DOS Ve 「 . 2 Ⅲ以上 あります。 型のカット & ペースト、コントロールキーのカスタ プ丿タの特徴を生かし実行時の致命的なエラーを メモリ・ 384K バイト以上 ( フリーエリア ) マイズなど ) の他に、プログラミングを指向した機 監視する実行時工ラーチェック機能を内蔵してい 格 29 , 800 円 ( 消費税込 ) 価 能 ( ソースファイル上に見出しを付けて管理する機 ます。この機能によってユーザープログラムのバ 3 ーインスペクター SEED 三光金属株式会社シード事業部〒 578 大阪府東大阪市菱江 707 お問い合せ・お申し込み TEL 0729 ー 65 ー 7225 ( 直 ) FAX 0729 ー 64 ー 4785

9. 月刊 C MAGAZINE 1990年10月号

学 五ロ 一三ロ mp をすると , 当然ながら暴走してしまうと いうわけて、す。 setjmp を使用する関数内て、レジスタ変数 を使っているときには注意が必要て、す。 たとえば List 4 を見てください。 printf て、 表示されるのはいくって、しようか ? f00 の 呼び出し直前に x を 5678 にしていますのて、 , f00 が longjmp して戻ってきたときにも x は 5678 のような気がします。しかし実行して みると , なんと 1234 と表示されてしまいま す。 これは x を「 egister として宣言した 問題があります。レジスタ変数は , ( 可能な らば ) CPU のハードウェアレジスタに割り付 けられます。そのため高速にアクセスて、き るし生成されるコードも小さくてすむとい setjmp を呼び出した場合には , 最新の setjmp うメリットがあるのて、すが , setjmp との組 gets(buf) : の呼び出しの環境が以前の環境を上書きし み合わせて、は , それがアダになってしまい atoi(buf) : てしまいます。したがって , env に対する のように書くのが定石のひとって、す。どち ます。 longjmp は最新の setjmp の環境へ大域脱出 setjmp て、格納される環境には CPU のレジ らかといえば , 筆者は後者のコーディング することになります。逆にいえば , 何箇所 スタも含まれています。ということは , setjmp をお薦めします。なぜなら scanf は意外と使 か大域脱出するポイントを設定したいとき の呼び出し時点て、の x の値が , env に保存さ いにくいからて、す。ファイルからの入力に には , それぞれ別の jmp buf 型変数を用意し fscanf を使うのはまだいいのて、すが , インタ れてしまっているのて、す。したがって setjmp なければならないということて、す。 ラクテイプな入力に scanf を使うとユーザが の次の x = 5678 は無視される形になります。 これはちょっと考えてみれば当然のこと 入力した改行の処理て、予期しない動作をす f00 か引 ongjmp て戻ってきたときには ,env なのて、すが , 不注意から同じ変数を使って の中に保存されていた 1234 が x の値として復 ることがよくありますから・・ このあた setjmp してしまって「へんな動きをする」と 活してしまうのて、す。 りの話は次の機会に説明しましよう。 悩む人がいるかもしれないのて、挙げておき 上記の入力方法て、は入力て、きるのはただ これを回避するためには , x をメモリに割 ました ( おまえのことだろうって ? ほっとい ひとつの数値だけて、 , 式を書くことはてき り付けるようにしなければなりません。通 てください ません。 C の標準ライプラリには式を入力し 常は明示的に reg ister と宣言しないかぎり , て評価する関数は用意されていませんから。 変数はメモリ ( スタック ) に割り付けられま 使用例ー式を評価する しかし , データを入力するときに簡単な計 す。 算をしてから入力したいような場合もあり しかし , LSI C ー 86 のように自動的にロー て、は setjmp/longjmp の応用例として , 式 ます。こんなとき , コンヒ。ュータにデータ カル変数のレジスタ割り付けを実行してし を評価するサプルーチンを作ってみましよ を入力しようとしているにもかかわらず , まう処理系て、は「 egiste 「と書かないだけて、は わざわざ電卓を取り出してきて計算し , そ 不十分て、す。 LSI C ー 86 の場合は # p 「 agma ューザに対して何か数値を入力させるよ no 「 egalo を指定してレジスタ割り付けを禁 の結果を入力するなどというバカらしい うなプログラムを C て、作成する場合 , scanf とをせざるを得ないのは惜しくありません 止するか , 明示的に 関数を用いて , autO int X : printf("input value?") ; と書きます。 ANSI C の規定て、は , setjmp て、はいっそのこと式を評価するルーチン を呼び出す関数内のローカル変数を vo ⅱ e を作ってしまいましよう。入力された 1 行を のようにするか , gets や fgets などの 1 行入力 と宣言することによってこの効果を得るこ パラメータとして受け取り , そこに書かれ 関数と atoi 関数を利用して , とがて、きることになっています。 た式を評価して , 計算した値を返します。 printf("input value?") ; 同一の jmp buf 型変数 env に対して何度も gets などて、 1 行を入力した後に atoi のかわり C 言語雑学講座 129 レジスタ変数の問題 List 4 1 : #include く stdio. h> 2 : #include く setjmp. h> 3 : 4 : jmp_buf env; 5 : 6 : V 0 i d foo ( ) 8 : i nt ma i n ( ) 20 : longjmp(env, register ニ 1234 : X if (setjmp(env) ニ 5678 : X foo() : printf("%dYn" i nt X :

10. 月刊 C MAGAZINE 1990年10月号

′学 五ロ 三一口 呼び出した関数の実行は一時停止し , 呼び 出された関数の実行が開始され , その処理 が終了した後に再開されます。この CALL/ RET の動作が関数呼び出しにおけるプログラ ムの実行順序の制御の基本て、す。 大域脱出 ところて , プログラミングをしていると きに , 次のような状況に出会うことがあり ます。 処理の内容をいくっかの関数に分割し , ある関数が別の関数を呼び出していて , そ の関数がさらに別の関数を呼び出している そしてこれが何重にも繰り返されて いる場合を考えてください。つまり関数呼 び出しが深くネストしている場合てす。各 関数はその処理中にエラーを検出すると値 ERROR を返すとしましよう。 この場合 , 工ラーをチェックしながら処 理を進めていくコードは List 2 のようになる て、しよう。関数のネストが深くなっている ときにエラーを検出した場合 , いちいち if 文 て、の判定を実行しながら処理を開始したト とが保証されます。ということは , 関数呼 ップレベルの関数に戻ることになります。 出したところから一気にトップレベルに戻 CALL / 日 ET の組み合わせて、関数呼び出しを実 び出しに関しては if 文によるエラーチェック ることがてきればとても便利て、す。ェラー 現している以上 , これはしかたがありませ を検出した時点て、トップレベルに戻ってし は不必要になりますね。 このように , 通常の関数のコール / リター まうのて、すから , 呼び出した関数から戻っ ん。 ンの動作をバイバスして上位の関数へ直接 、しこのような状況ては , 工ラーを検 てきたときにはエラーは発生していない しカ リターンすることを「大域脱出」といいます。 ネストした関数呼び出しでのエラー処理 大域脱出のために C 言語に用意された標準ラ イプラリ関数が setjmp と longjmp て、す。 etjmp と longjm setjmp のプロトタイプ宣言は次の形をし ています。 int setjmp(jmp buf env) : jmp ー buf 型は現在の環境を格納するための 型て , setjmp. h の中て定義されています。 こていう「環境」とは環境変数のことて、はな く , リターンアドレスやスタックポインタ やそのほかのレジスタなどの CPU の実行環 境のことてす。 Fig. 2 Fig. 1 が実行されたときのスタックのようす Low Address CALL—printf の 次のアドレス CALL—main の 次のアドレス CALL—main の 次のアドレス CALL—main の 次のアドレス High Address (a) main の先頭 (b) printf の先頭 (c) p 「 in 廿から R ETC 戻ってきたとき 単純な関数呼び出しの例 int printf(char *p, / * pr i ntf のコード ( 省略 ) * / 3 : 5 : 6 : 7 : int main(int argc, char *argv[]) printf("hello worldYn"); 9 : 10 : } List 1 2 List f3() int i f ( 工ラーを検出した ) 3 : (ERROR) : 4 : return 7 : f2() 8 : i nt if (f3() ーニ ERROR) (ERROR) : return 14 : fl() 15 : i nt if (f2() = ERROR) 17 : (ERROR) : return 20 : } c 言語雑学講座 127