C 十十 プログラミング 入門 のほうが大きいと思います。 また , g 十十には , 先に紹介した libg 十十 があるのも大きな特長て、す。なお , gcc と g 十十 についてさらに , 本号の吉田氏の記事も参 考にしてください ・ C 十十 3.0 C 十十 3.0 の仕様は , まだはっきりしてい ません。しかし , 参考文献 [ 2 ] ても述べら れているように , パラメータつきクラス (Parametric CIass) と例外処理 (Excep tion Handling) が導入されることは , ほば まちがいないてしよう。前者のパラメータ 付クラスは , すてに紹介した ( 本連載第 3 回 参照 ) のて、 , ここては後者の例外処理を紹介 しましよう。 ・例外処理 まだ C 十十の例外処理の仕様は , パラメ ータ付クラスほど明確には決まっておらず , 参考文献 [ 2 ] ても詳細は解説されていませ ん。ゆえに , 以下に紹介するものが , すっ かり C 十十 3.0 て採用されるかどうかはわか りません ( 注 23 ) C + 十の例外処理機構は , 名前のとおり , プログラムの例外 , つまり , 数値演算の際 のオーパフロー ( あふれ ) , 配列の領域外の アクセス , NULL ( のての除算 , ヒープ領域 の不足などのアルゴリズムの記述とは関係 ない ( 本質的てない ) 処理を取り扱う標準的 な方法を提供し , パラメータ付クラスと同 じように , 大規模なライプラリの構築のた めには , 不可欠なものてす。 例外処理を考えましよう。 List11 に簡単な 例を示します。この例ては , 関数 oops て、例 外が発生するかもしれないとします。した がって , 関数の頭の部分て , 例外かどうか の検査をしています。もし例外だったら , 必要な情報を例外の型に詰め込み , th 「 ow 文 て投げ飛ばします。ここて , 情報を詰め込 んだ例外の型のオプジェクトは , List11 の先 頭にクラス oops ー tl , oops t2 として定義し 注 23 例の例外処理のプログラムは , 現時点ての最新の 情報をもとに作成しました。 98 CMAGAZINE 19 囲 7 てあります。 th 「 ow 文て投げ飛ばされた例外の型のオプ ジェクトを受け取り , 処理を行うのが , try 文と対になった catch 文群てす。 t 「 Y は , 例外 が発生しそうな部分をプロックとして囲み , そのブッロクて発生した例外を後続の catch が処理するのてす。 catch は , 例外の型ごと に用意され , それぞれ例外に対する適切な 処理が記述されます。 0 まとめ このように , C 十十は徐々に機能が追加さ れ , 大きな仕様をもった言語になろうとし ています。また , 言語の標準化も ANSI の X3 J16 委員会 (ANSI C 十十 ) て行われているよ うてす。ついに , C 十十も興味をもつ必要の ない言語になりそうてす。個人的には残念 てすが , C 十十も大衆の言語となってしまう のてしよう ( 本誌 18 頁参照 ) 。 ただ , すべての C プログラマが C 十十に移 行するかどうかは , まだわかりません。そ れは , C 十十の言語仕様が C に比べて , 複雑 なためてす。 C は , 高級アセンプラとも呼ば れ , 慣れた人なら , コンパイル後のコード をも意識したプログラミングが可能てす。 それは , ソースコードと機械語コードにあ る程度の対応があったからて、す ( つまり , 余 計なことをしない ) 。これは , 考え方によっ ては初心者にとっても理解しやすいわけて、 す ( 勝手に妙なことをされるよりは ) 。しか し , C 十十は , 多機能ゆえに , 処理系が勝手 にさまざまな処理を行います。たとえば , 派生クラスのコンストラクタ呼び出しは , 勝手に基底クラスのものまて呼び出します し , メンバ関数ては , 暗黙の引数があった りします。それら , おせつかいなような処 理は C 十十には不可欠なものてすが , C 十十 の学習を始めたばかりの人は , それて、ずい ぶん頭を悩ませているように思います。そ ういう困難を乗り越えて , C 十十を使いこな し , 自分て、優れたクラスを設計し , 実装て、 きる人は , そう簡単には増加しないてしよ しかし , C 十十があまり使われないといっ ているのてはありません。 C 十十は , 多数の ューザに使われるてしよう。それは , て紹介した , 新たに追加された機能が , 大 規模なクラスライプラリの構築を指向した ものだからてす。つまり , libg 十十 , NIHCL, InterViews などのライプラリ , さ らに大きな , 優れたライプラリがたくさん 登場すれば , ューザはクラスを自分て、作成 せず , 既存のライプラリを使うことて , C 十十 を使うことがてきるわけてす。前にも述べ たように , C 十十を C よりわずかに優れた言 語として利用することは , そんなに難しい ことて、はありませんから , こうした C 十十の ューザはどんどん増えるてしよう。 参考文献 [ 1 ] Stroustrup, B. , 「 The C 十十 Pro gramming LanguageJ Addison-WesleY' 1986. [ 2 ] Limmpan, S. B. , 「 C 十十 Primer 』 Addison-WesIey, 1989. [ 3 ] Lea, D. , fUser's Guide t0 GNU C 十十 Library 』 Version1. 35.0 , FSF, 1989. [ 4 ] Linton, M. A. , Calder P. R. and Vlissides J. M. , TInterViews : A C 十十 Graphical lnterface T001kitJ ln Proc. USENIX C 十十 Workshop, 1987. [ 5 ] VIissides J . M . and Linton, M . A. , 「 Applying Object ー Oriented Design to Structured Graphics 』 InProc . USENIX C 十十 Conference, 1988. [ 6 ] Linton, M. A. , Vlissides J. M. and CaIderP. R . , fComposing User lnter faces with lnterViewsJ Computer, 1989.
ラムとリンクをしようとすれば困ったこと になります。 C 十十 1.2 ては , キーワード overload を使 ったり , 関数群の最初の関数の名前は符合 化しないなどの姑息な方法を使っていまし たが , 複数のライプラリを使うときなどに 問題がありました。 C 十十 2.0 て、は , 名前を符合化しない関数 を , 以下のように明示的に指定てきるよう になりました ( 残りの関数は , すべて符合化 され , キーワード overload は不要になっ た ) 。 コンストラクタ コンストラクタ はないため , C や FORTRAN などのプログ 符合化された名前は , もはやもとの名前て、 f 0FPc という識別子が使われる ) 。しかし , とえば , f (int) は f 0Fi という , f(cha 「 * ) は 受けつけように符合化し , 渡しています ( た 義された関数名を , リンケージェデイタが 名前は受け付けません。 C 十十て、は , 多重定 デイタ (UNIX の ld など ) は , ュニークてない を生みだしますが , 大部分のリンケージェ の関数の多重定義機能は同じ名前の関数群 名前の問題がありました。というのは , C 十十 また , C 十十 1.2 ては , リンク時に若干の VO i d oops-tl (String s) String os; struct oops-t2 { / / 例外の型その 2 List 1 1 oops-tl (lnteger i) lnteger Oi : struct oops-tl { / / 例外の型その 1 例外処理の例 oops(String as, lnteger (i) { / / 例外が発生するかもしれない関数 / / まず例外かどうかを検査する if ()s = NU ししⅡ as = throw oops_t2(as) : i f (a s ー throw oops-tl (ai) : / / 本質的な処理 "gomi") { / / 例外だったら , 処理部に投げ飛ばす / / 例外だったら , 処理部に投げ飛ばす VO i d main(void) { String name : lnteger uri : / / 適当なサンプル try { / / このプロックで発生した例外は , 後続の catch が処理を行う / / 例外型 oops ー t2 の例外処理 catch (oops-t2 (2) { / / 例外の型が oops-t2 だったら . くく a i くく " が与えられた。こんなことちゃ困ります Yn" : cout くく " 関数 main から呼ばれた関数 oops で , 引数 ai に " / / 例外型 oops - tl の例外処理 catch(oops-tl (l) { / / 例外の型が oops-tl だったら .. oops(name, uri); / / 例外が発生しそうだなぁ . extern "C" int fprintf(const char*, また , プレース { } て囲み複数の関数 ( へ ッダファイルの # inc 旧 de 文てもよい ) を指定 してもかまいません。 ・ const メンバ関数 const メンバ関数は , C 十十 2.0 から用意 されたものて、す。 const メンバ関数というの は , インスタンスの情報を変更しないメン バ関数として宣言されます。たとえば , const F00 aFOO ; と宣言された aFoo に対し , 操作を許すメン バ関数を指示するわけて、す。クラス F00 の定 義が以ドのようだとすると , class F00 { private : public : lnteger get (void) const ; void insert(lnteger) ; メンノヾ関数 se 「 t は , ふつうのメンノヾ関数 てすから , aFOO . insert(0) : は , 工ラーになります。しかし , get は , const メンバ関数と宣言されていますから , lntegerg=aF00. get( ) ; というように , const のインスタンスに対 し , 操作を行うことがてきます。 ■ g 十十 g 十十は , FSF の gcc をもとに作成された 真の (native) コンパイラてあり , gcc 同様 , かなり優れた性能をもっています。 g 十十 は , かなり頻繁にバージョンアップされて おり , 最新の 1.36.2 は AT & T の C 十十 2.0 の仕様をほば満たしています。ただし , g 十十 は , AT & T の処理系をもとにせず , 独自の 実装を行っているため , 細部の動作が若干 異なるところがあります。しかし , 筆者が 気づいた動作の違いは , たとえ指摘したと ころて , 重箱の隅をつついているようなも のて , あまり気になりません。それよりは , 無料てソースコードが手に入る g 十十の魅力 C 十 + プログラミング入門 97
LANGUAGE 致命的工ラー処理の 1r0 れ 5P0 「 e れ蓄 ( 「 E 汁 0 「 Ha れ引 ing Danny 、 awrence/ 岩谷宏訳 COMPUTER LANGUAGE/April 1989 ) 提携記事 BITST—SNC 透明化 ー物題満 Tm い : ・ CA 孖を INA ー田日 E 日 A S 致命的工ラーの処理は , それぞれのプロ グラムに合った方法て行うべきて、す。 MS- DOS が画面に出す「中止く A 〉 , もう一度 く R 〉 , 無視く I> ・ ? 」というメッセージて、十分 なプログラムもあるて、しよう。その一方て、 , ウインドウをオープンしてメッセージを画 面の下に出す , などの複雑な処理を必要と するプログラムもあります。このように プログラムによって要件が違うために , 致 命的ェラーのハンドラは , プログラムごと に作るのが普通て、す。ただそれは , アセン プリ言語て、書いておいて , プログラムごと にユーザインタフェイスの部分だけを書き という場合が多いのて、 , そ 換えればよい れほどめんどうな作業て、はありません。 本稿ては , 汎用的な致命的工ラーハンド ラ用の低レベルの細部的な処理を引き受け , ューザインタフェイス関数はそのつど自由 に書ける , というシステムについて説明し ます。 MS-DOS の 致命的ェラー処理 MS-DOS が INT21H のファンクションの サービスを実行しているときに , 深刻な工 ラーが起こると , 必ず致命的工ラーハンド ラをコールします。このハンドラは , ユー 22 CMAGAZINE 19 7 ザにエラーを説明して , 指示を待つものて、 す。デフォルトのハンドラは , おなじみの 「中止く A 〉 , もう一度く R 〉 , 無視く I> ? 」メ ッセージて , ューザによって囚 , 囮 , または 国キーが押されるのを待ちます。これとは 別のエラー処理をさせたいときは , ハンド ラを自分て、書かなければなりません。 ハンドラに制御が渡ったとき , スタック とレジスタにはエラーに関する情報と , MS TbI.1 スタックの内容 SP からのオフセット 十 00h 旧 十 02h CS 十 04h Flags 十 06h AX 十 08h BX 十 Oah CX 十 Och 十 Oeh 十 1 Oh 団 十 1 2 h B P 十 14h DS 十 1 6 h ES 十 1 8 h 旧 十 1 ah CS 十 1 ch TbI.2 FIags DX MS ー DOS へのリターンアドレスとフラグ 旧 ET で MS ー DOS ヘリターンする アプリケーションのレジスタ ー DOS とユーザアプリケーションへの , 両方 のリターンアドレスがあります。スタック のようすを TbI. 1 に示します。スタックトッ プは , MS ー DOS への旧 ET 用に設定されてい ます。その下に , アプリケーションのレジ スタ , リターンアドレス , そしてフラグが あります。 レジスタには , 以下に述べるようなエラ ーの理由と所在に関する情報が入っていま す。 ・団レジスタの下位バイトには , 工ラーコー ドがあります。上位バイトは未定義です。 Tb に 2 に , 工ラーコードとその意味を示し ます ・ BP : に , 工ラーを起こしたデバイスの デバイスへッダ ( = デバイスドライバのヘ ッダ部 ) の制御プロックへの far ポインタが あります アプリケーションへのリターンアドレス にあるエラーコード 10 進数 工ラーコード 書き込み保護のティスクに書き込もうとした そういうドライプ ( ~ 装置 ) は存在しない ドライプの準備ができていない ( 装置のドアが開いているなど ) 存在しないコマンド ( テパイスドライバがサポートしていないリクエスト ) データの CRC 工ラー リクエストのサイズの不正 シークエラー セクタが存在しない プリンタが用紙切れ 書き込み工ラー 読み出し工ラー 一般的なティスク不良 [ 注 ] 、、リクエスト″とはテパイスドライバへのレ O リクエストのことである。 10 9 8 6 5 4 3 2 1 0
List3 込みます。 gperf 自体は「いかむ」さんが X68000 に g 十十を使って移植 , 公開されまし たのて , これを使用させていただきました。 後は , 宣言を処理する c decl. c に引き渡す変 数 redpointers に qremote" 記憶クラスを定 義し , ヘッダにもこれを追加すれば , 文法 部分の修正は終了て、す (List2)0 こまて、は 2 時間もかからない作業て、したが , 本番はこ れからて、す。 この修正を終わって , コンパイル , リン クしたコンパイラは「 emote 宣言は受け付け ますが , 具体的なコードの改変 , および違 法な宣言をリジェクトしません。セマンテ イクスな処理がまだまったく記述されてい ないからて、 , この状態だと普通の外部宣言 になります。 セマンティックス処理をつかさどる c decl. c に手を加えるわけて、すが , いきなりソ ースに目をとおしても , 3900 行にものばる ソースコードを理解するのは容易て、はあり ません。そこて、 , いささか手抜きかもしれ ませんが , g 「 ep に登場してもらい ,EXTERN を検索させます。先ほども述べましたが文 法的に extern と同様なのて , その文字まわり の処理を参考にすれば間題ないはずて、す。 泥縄的てすが , 今のところ正しく処理され ていますからだいじようぶてしよう。 List3 から List9 がその具体的な変更てす。 大文字て関数のように見えるのはすべてマ クロてす。 List3 構造木のフィールドに remote アトリビュートを追加する GCC の構文木の共通属性部分に「 emote atter として 1 ビット , ビットフィールドを 追加します。これがその変数の具体的な記 憶クラスを示しています。さらに , そのア トリビュートにアクセスするマクロを定義 します。 List5 再宣言された場合にその属性を木 構造にコピーする処理を追加 再宣言された場合にその属性をコヒ。ーす る処理に REMOTE 属性を追加します。 をーい第ーいにいー 第 tree. h- in same compiler run. tree. h-#define TREE_UID(NODE) ( (NODE) ー〉 com田 on. uid) LiSt 属性にアクセスするマクロを定義する い一し ( り町いいいいい—りにり - いにい tree. h- tree. h:/* add OSK data class remote * / tree. h:/* non zero data C lass iS * / tree. h- tree. h: #define TREE_REMOTE(NODE) ((NODE)- 〉 common. remote_attr) tree. h- List 再宣言された場合にその属性を木構造にコピーする処理を追加 TREE_TYPE (olddecl) : TREE_TYPE (newdecl) : TREE_READONLY (olddecl) ニ TREE_READON し Y (newdecl) : TREE_THIS_VO し ATILE (olddecl) = TREE_THIS_VO し ATILE (newdecl) : TREE_VOLATILE (olddecl) ニ TREE_VOLAT ILE (newdecl) : / * Merge the storage c lass information. if (TREE_EXTERNA し (newdecl)) TREE_STATIC (newdecl) = TREE_STATIC (olddecl) : TREE_REMOTE (newdecl) : TREE_REMOTE (olddecl) : TREE_EXTERNAL (newdecl) : TREE_EXTERNA し (olddecl) : / * functions, overrides non—static. if (TREE_CODE (newdecl) = FUNCTION_DECL) TREE_PUB い C (newdec l) & = TREE_PUB い C (olddec l) : / * This is since we don't automatically COPY the attributes Of NEWDEC し intO 0 し DDEC し . TREE_PUB い C (olddec l) = TREE_PUB い C (newdecl) : / * け this clears static ・ , clear it in the identifier t00. if ( ! TREE_PUB い C (olddecl)) TREE_PUBLIC (DEC し _NAME (olddecl)) e lse { TREE_PUB い C (newdecl) = TREE_PUB い C (olddecl) : e ー se TREE_STATIC (olddecl) TREE_REMOTE (olddecl) TREE_EXTERNAL (olddecl) TREE_PUB い C (olddecl) = TREE_STATIC (newdecl) : = TREE_REMOTE (newdecl) : = TREE_PUB い C (newdecl) : / * け either decl says inline', this fn is inline, unless its definition was passed already. * / if (TREE_I N い NE (newdecl) & & DECL_INITIAL (olddecl) = TREE_IN い NE (olddecl) / * け redeclaring a builtin function, and not a definition. List 己憶クラス複数のチェックルーチン変更 一三ロ warning ( " ニ重の VO ね t Ⅱ e です " ) : c decl. c- type ニ TYPE_MAIN_VARIANT (type) : c_decl. c- c_dec l. c- / * Warn if two storage classes are given. Default tO autO ・ c decl. c- c_decl. c- c_decl. c- c_decl. c- c_decl. c- c_decl. c- c_decl. c- c_decl. c: c decl. c- c _dec l. c- c decl. c- c_decl. c- c_decl. c- c_dec l. c- int nclasses : 0 : if (specbits & 1 くく (int) RID-STATIC) nclasses + + : if (specbits & 1 くく (int) RID-EXTERN) nclasses + + : if (!nclasses & & specbits & ーくく (int) RID-REMOTE) nclasses + + ; / * modify for OSK * / if (specbits & 1 くく (int) RID-AUTO) nclasses + + : if (specbits & 1 くく (int) RID-REGISTER) nclasses + + : if (specbits & 1 くく (int) RID-TYPEDEF) nclasses + + : / * Warn about storage classes that are invalid fO 「 certain kinds Of declarations (paraneters. typenanes. etc. ). Conference Room 137
C 十十 プログラミング 入門 る方法 (type-safe linkage) も提供されてい 口まとめ ます。多重継承 , 仮想基底クラス , クラス ー最近の C 十十事情 メンバへのポインタなどについては , すて、 3 つのクラスライプラリを紹介しました に解説しました。演算子の多重定義は , 1.2 が , これら以外にも市販の処理系に付属し 最近流行のオプジェクト指向プログラミ て、は多重定義て、きなかった ているものなどがいくつかあります。こう ングの重要な概念てあるデータの抽象化と , への多重定義が可能になり , アクセス領域 したクラスライプラリの存在は , プログラ を制限したポインタなどが新たに定義て、き 現在アプリケーション開発の主流言語てあ ムの開発効率を劇的に向上させる鍵になる ます。また , 自由記憶を管理する演算子 る C を絶妙のバランスて、融合した C 十十は , て、しよう。 "new" や "delete" も多重定義て、きます。 今後 , この分野て、大きな役割を担うて、しょ 個々のアプリケーションに適合した一五 に 1 ロロ これらは , ファイルスコープのものまて、定 う。ここては , その C 十十の最近の話題を中 は , その分野のプログラム開発を容易にし 義て、きるため , 新たに記憶管理の機構を再 心に , 新しい C 十十の機能などをの概要を紹 ます。科学技術計算には FORTRAN が , 銀 構築することが可能になっています。 行業務などの事務処理には COBOL が積極的 介します。 に用いられています。ほかにも文字列 , 複 なお , 純粋仮想関数 type-safelinkage, ロ最新 C 十十 素数 , 行列などのデータ型が使える言語は const メンバ関数は , 以下てそれぞれについ C 十十は , まだまだ成長している言語て、 て解説します。こうした機能の追加と同時 いくつかあります。しかし , それらすべて す。したがって , 徐々に新しい機能が追加 いくっか仕様も変更されています。た のデータ型をある言語に実装することは可 され , 処理系もどんどん進化しています。 とえば , 多重定義された関数の照合のアル 能て、あっても , 優れた方法とはいえません。 1984 年にリリースされた C 十十 1.0 は , 1986 現実に , すべての目的に適合するように ゴリズムが変更されたりしていますが , 年には 1.1 になり , また 1987 年には , 1.2 が こて、は , その詳細には触れないこ 非常に豊富な機能をもった言語が設計され 現れました。さらに , 昨年には , さまざま たこともありました。ただ , その仕様は , す。 な新しい機能が実装された C 十十 2.0 が発表 ・純粋 ( pu 「 e ) 仮想関数 巨大て、 , 理解しづらいため , あまり受け人 され , また C 十十 3.0 への進化さえ噂されて 本連載第 5 回て、も述べたように , クラスの れられていません。 C 十十は , クラスライプラリの充実によ 階層構造をもっ場合 , 上位のクラスは , 仮 います。 Stroustrup の参考文献 [ 1 ] には , C 十十 り , 個々のアプリケーションとの適合が可 想関数群により , 下位の関数のインタフェ 1.0 まて、の仕様しか解説されていませんが , 能て、あり , クラスを使うだけの ( クラスを設 イスを指示することがあります。そうした ほとんどの場合に , 仮想関数には , 処理自 計することをしない ) ューザは , 実際 , 既存 現在ほとんどの処理系は , 最低 C 十十 1.2 の 仕様 ( つまり , protected の保護メンバが導入 のライプラリから適当なクラスを選ぶだけ 身が用意されません。 された仕様 ) まて、は満たしており , 進んだ処 て、 , プログラム開発効率は飛躍的に向上て、 C 十十 2.0 て、は , インタフェイスの指示の 理系はすて、に C 十十 2.0 の仕様に達していま ための , 処理が記述されない仮想関数を純 きます。さらにクラスの派生などにより , す。加えて , FSF の g 十十は , C 十十をほば クラスの拡張 , クラスのカスタマイズなど 粋仮想関数と呼びます。純粋仮想関数は , 満たした処理系として公開されています。 を行えば , より目的に合致したクラスを使 以下のように 0 て初期化することて宣言され 以下に , これら新しい C 十十の特長を簡単に うことがて、きます。あたかも , それが言語 ます。 仕様の一部てあるかのように・ classgomi { 説明したいと思います。 ただ , 残念なのは , 公開されているクラ public : ・ C 十十 2 ℃ スライプラリの数がまだまだ少ないことて、 vi 「 tual VOid move (void) あり , その標準化がされていないことて、す。 C 十十 2.0 は , 1.2 にいくつかの機能が追 , こて、紹介するクラスライプラリは , まだ 加され , 関連した仕様の変更が行われまし 一部の計算機て、しか動作しません。移植も た。追加された機能には , 多重継承 , 仮想 これて move ( ) は , 純粋仮想関数になり , 徐々に進んて、いるようて、すが , MS-DOS 系 基底クラス , 純粋仮想関数 , const メンバ関 したがって , このクラス gomi のインスタン の計算機て、はまだ利用て、きないようてす。 数と static メンノヾ関数 , 、、 new", スは , 生成て、きません。つまり , gomi は , そして , C 十十自身の標準化の準備が始まっ ー > 〃などの演算子の多重定義 , ク 派生クラスを作成するためだけに使われま た段階てすから , 基本的なクラスライプラ ラスメンバへのポインタなどが多数ありま す。 リの標準化はまだ先になることて、しよう。 リンク時の名前の問題を回避す ・リンク時の名前の問題の回避 す。また , 96 CMAGAZINE 19 7
ー最新入門 特集 GCC / 十十の展望 Pa rt 吉田英樹 GNU プロジェクトで開発された C コンパイラ GCC は , 安定性 , 移植性 , コードの効率などか評価され , 広く使われている。 こでは , GCC の背景 , 使い方 , 最適化や , インラインアセンプ ラ命令 , RTL 表現などのわかりづらい点について説明する。ま た , configu 「 ation および移植についても触れる。最後に , G CC 2.0 の展望を述べる。 ftp するのがよい。日本国内にも , utsun. s. u-tokyo. ac. jp など , GNU のソフトを置い ている anonymous ftp site がいくつかあ GCC は ,GNU プロジェクトの一環として の解決策 , および新しい機種への移植情報 また , g 十十は GNU 版の C 十十コンパイラ 開発された C コンパイラてある。現在発表さ ニュースとして流されている。これら カ てある。ほかのほとんどの C 十十コンパイラ の情報は , 頻繁に行われるバージョンアッ れているフリーソフトウェアの C コンパイラ カ℃言語へのプリプロセッサとして実現され としては , 安定性 , 移植性 , コードの効率 プに反映され , 現在配布されている GCC ているのに対して , g 十十は直接ネイテイプ などの多くの面て , 最高レベルの処理系て Ver. 1.37.1 ては , 多くのユーザのハードな コードを出力するのて , コンパイル速度な あるといえる。 使用によって , ほとんどのバグが洗いつく どの面てかなり有利となっている og 十十コ 何よりも優れているのは , そのサポート ンパイラのコードは , かなりの部分が GCC され , 信頼度の極めて高い処理系となって 態勢てある。もちろん , GCC がフリーソフ のコードと共通になっているのて , GCC に いる。 トウェアてある以上 , 作者の R. StaIIman た 加えられた変更は , そのまま自動的に g 十 + GCC 自体もネットワークを通じて配布さ ちにも Free Software Foundation (FSF) にも適用される場合が多い。具体的には , れているの <,lnternet などに IP 接続されて にもサポートする義務はないのだが , 現実 GCC< なんらかのバグが取れると , g 十十て いるサイトてあれば , 新しい処理系をバー には , 商品として販売されている処理系と ジョンアップと同時に入手することがてき も同じバグが解決されることがあるし , あ 比較しても , きわめて素早い対応が得られる。 る機種に GCC が移植されていれば , 新たな る。 prep.ai.mit.edu が GNU のホームサイ たとえば , アメリカを中心とした大規模 こから anonymous ftp 手間をほとんどかけずにその機種て g 十十を トとなっており , ネットワークてある USENET< は連日 , GCC て最新バージョンが取得てきるが , 遠距離 動かすことがてきる。 の作者たちはもちろん , GCC を使用してい , こに接続すると転送に時間がかかり GNU プロジェクトては , Pascal および る多くの一般のユーザから , バグ情報やそ すぎる。手近なサイトを探して , そこから FORTRAN などのほかの汎用プログラ、 、ン はじめに 特集最新 GNIJ 入門
・関数 qso 「 t と bsreach の比較要素は , void * て、渡される ・値て、返される st 「 uct の取り扱い方法が変史 されたため , Turbo C 2.0 て、作成したラ イプラリとリンクすると , 間題が発生す る ・ C 十十は型の検査が厳しいため , プロトタ イプの型検査などて、 , Turbo C 2.0 て、は 発生しなかった警告が発生する ・ Turbo C 2.0 とは , レジスタ割り付けに 相違があるため , 特定のレジスタ割り付 けを想定して記述したインラインアセン プラは動作しない可能性がある プラグマの追加 従来 , 関数 main( ) の前処理を変更しよう とすれば , スタートアップコードに修正を 行っていたが , 新たに追加された sta 「 tup プ ラグマにより , 最大 192 の関数をスタートア ップ時の処理として指定することが可能に なった。同様に , 関数 main ( ) の後処理を行 う関数を指定するために , exit プラグマも追 加された。 ほかのプラグマとして , 次のもの が追加された。 ・ argsused : 関数定義間の相違などにより 生じた警告メッセージの無効指定 ・ option: コンノヾイルオプションをプログ ラム中て、指定 ・ in line : インラインアセンプリのコードを コンノヾイラに孑旨疋 ・ warn : 無視を行う警告メッセージの指定 ・ save 「 egs : 大きな関数て、の , レジスタ値 の勝手な変更の制限 ドキュメンテーション Turbo C 2.0 のマニュアルカ℃言語のよい 解説書になっていたのと同様に , Turbo C 十十に付属するマニュアルが , C 十十のよ い言語マニュアルおよびチュートリアルに なることを願っている。ポーランドジャパ ンの翻訳作業にも期待したい。 また , ポーランド社から C 十十が販売され ることて、 , C 十十 2.0 の解説書が増えること も期待て、きるだろう。 プロクラマーズ プラットホーム Turbo シリーズの従来の統合開発環境を 発展させ , 「プログラマーズプラットホーム (Programmer's Platform) 」と名づけた。次 にその特徴を紹介しよう。 工テイタ ・マルチファイル , マルチウインドウがっ いに実現された。ファイルやウインドウ の数に制限がない なお , ウインドウは , オーバラッヒ。ングウインドウて、あり , ウ インドウの移動およびサイズ変史が可能 て、ある。また , ウインドウ間のカット & べーストやヘルプウインドウのコードの コヒ。ーが可能て、あり , クリップボードも 用意されている。さらに , 編集可能なフ 工デイタがマルチファイル , マルチウィ えて , プラットホームを独自に設定て、き (Turbo Editor Macro Compiler) に ロやキーの定義を許し , それを TEMC Macro Language) は , ユーザによるマク マクロ言語 TEML(Turbo Editor トされた。 ・各種マウス (MS,Logitech など ) がサポー イルサイズの制限はない ァイルには , ディスクサイズ以外にファ イルサイズはディスクサイズ以外に制限要 タの機能まて、には達したようて、ある。ファ 能により , 少なくとも , 日本の市販工ディ オーバラッヒ。ングまて、可能だ。これらの機 サイズ , 位置とも変更可能になり , さらに た 0Turbo Debugger と同様に , ウインドウ インドウ間のカット & ペーストも可能になっ の市販工デイタて、は常識になっている , ウ ンドウになったのはうれしい。また , 現在 因はない マウスのサポートもオーバラッヒ。ングウ インドウて、は有用だろう。ウインドウ番号 が隠れていてもウインドウの一部が見えて いれば選択て、きるわけだ。 また , ファイル位置変更は , 賢いキャッ シュ機構 (intelligent caching) により , どこ へて、も一瞬て、移動て、きるという ( 「一瞬 (in stantaneus) 」とは何秒ぐらいなのか試してみ たいものだ ) 。 カット & ペーストて、は最大 64KB のクリッ プボードを使える。 マクロ言語は , ASCII ファイルとしてエデ ィットコンパイルし , プログラマーズプラ ットホームに組み込むことて、使用可能にな T 「 ansfe 「オプション プログラマーズプラットホームから , ほ かのプログラムを起動するとき ( たとえば , Turbo Assembler など。インラインアセン プラを使用すると , 指定のアセンプラが自 動的に起動される。 TASM, MASM が使用 可能 ) のオプションをあらかじめ設定する と , プログラムの出力をメッセージウイン ドウに取り出せる。プログラムの結果て、あ るトランスフア出力て、 , 工デイタからスペ ースキー , またはカーソルキーて、ステップ するたびに , 該当するファイルを自動的に オープンし , 該当する行へカーソルを移動 してくれる。いままて、 Turbo C て、しか利用 て、きなかったタグジャンプが , トランスフ アオプションの設定て、 , Assembler や grep な どの出力に対しても可能になった。 Transfer メニューて、選択されたプログラ ムを実行するときには , プログラマーズプ ラットホーム自身のメモリ使用量は自動的 にスワップされ , 削減するのて、 , メモリ不 足の問題は起きにくい プロジェクトマネージャ 組み込みの make を使ったプロジェクト管 20 CMAGAZINE 1990 7
C 十十 プログラミング 入門 0 れます。 InterViewsC' は , オプジェクトへ の操作や処理の集合をまとめて , 通信プロ トコル ( あるいはたんにプロトコル ) と呼び ます。ここては , 各オプジェクトに定義さ れた通信プロトコルについて解説します。 teracto 「の通信プロトコルには , List5 に 示すようなものがあります。操作 D 「 aw は , lnteractor を描画し , 操作 Resize は te 「 acto 「の大きさの変更処理を行います。 te 「 acto 「へのイベント処理関係ては , 操作 Read が待ち行列からイベントを取り出し , 操作 Handle が処理します。これらのプロトコル は , lnteractor クラスから派生したクラスに も受け継がれ , InterViews のすべてのオプ ジェクトは , これらの操作については共通 のインタフェイスをもっことになります。 Scene のプロトコルて、は , さらに List6 の ようないくっかの操作が追加されています。 scene の構成要素としての旧 te 「 actO 「オプジ ェクトは , 操作 se 「 t や Remove て、指定しま す 0Tray や Deck などのオプジェクトて、の構 成要素の順序は , 操作 Raise や Lower< 変更 します。 同様に Graphic や Text, さらに派生した Picture や Clause にも , 追加されたプロトコ ルがあります。たとえば ,Graphic には , List7 のような図形の移動 , 回転 , 拡大 , 縮小の ためなどの操作が追加され , CIause には , List8 のようなテキストの挿入や置換のため などの操作が追加されています。 このように , . クラスの派生により , 必要 に応じて新しいプロトコルが追加されます。 プロトコルのほとんどは仮想関数て、あるた め , 統一的な取り扱いを保ったまま新しい 処理に置き換え , 動的束縛を使った処理の 選択を利用することもてきます。なお , れらのプロトコルの具体的な使用法は , 次 のプログラム例を参考にしてください ■プログラム例 さて , ここ <InterViews を使って , プロ グラムを作成してみます。まず , List9 に簡 単な例を示します。ウインドウの土台とな 94 CMAGAZINE 19 7 List 9 24 : main(int argc, char* argvC]) { / / ウインドウの基礎となる Wor ld オプジェクトを生成している。 25 : 〃同時に , コマンド行のオプションも解析している。 26 : new World("gomil", ps, OS, argc, argv); 27 : World* kumi 28 : / / メッセージ本体である Message オプジェクトを生成している。 = new Message(" SOFTBANK C MAGAZINE 30 : Message* m / / 表示しようとするオプジェクトを World オプジェクトに挿入する。 32 : kumi->lnsert(m) : 33 : 34 : / / イベント待ち 35 : kumi->Run() : 36 : 旧 te Ⅳ iews のプログラム例 2 List 1 0 2 : * * プログラム gom i 1. cc の文字列にスクローラをかぶせたプログラム (gom i 2. cc) 3 : 4 : 5 : / / InterViews のヘッダファイルの読み込み 6 : #include く InterViews/defs. h> / / InterViews ワールドの構築のための定義。 7 : 8 : #include <InterViews/border. h> / / Border オプジェクトの定義。 9 : #include く InterViews/box. h> / / Box オプジェクトの定義。 10 : #include く InterViews/message. h> / / Message オプジェクトの定義。 11 : #include く InterViews/scrolIer. h> / / Scroller オプジェクトの定義。 12 : #include く InterViews/viewport. h> / / Viewport オプジェクトの定義。 13 : #include く InterViews/worId. h> / / World オプジェクトの定義。 14 : 15 : / / このプログラムは , スクローラ ( スクロールバー ) により , 一部分だけを表示する 16 : / / ような文字列のウインドウを生成するものである。 InterViews TooIkit では , 17 : / / テキストやグラフィックスまでオプジェクトとして管理するため , このようなこ 18 : / / とは容易に可能である。 20 : / / リソース情報の指定にこでは , フォントの種類を指定している ) 。 21 : static PropertyData ps[] {"*font" 22 : -*-heIvetica-boId-r-normaI--34-*"}, { n i I } 23 : 24 : } : 25 : / / プログラム個有の追加オプションの情報の ( なし ) 記述。 26 : static 0ptionDesc os ロ 28 : / / ただの ma i n 関数 VO i d 29 : main(int argc, char* argv ロ ) { / / ウインドウの基礎となる Wor ld オプジェクトを生成している。 30 : / / 同時に , コマンド行のオプションも解析している。 32 : World* kumi ニ new WorId( ” gomi2" ps, OS, argc, arg の : 33 : / / メッセージ本体である Message オプジェクトを生成している。 34 : 35 : Message* ニ new Message(" SOFTBANK C MAGAZINE 36 : / / 生成した Message オプジェクトにスクローラをかぶせ , その一部 / / だけを表示できるようにする。 38 : / / まず , Message オプジェクトを構成要素の一部だけを表示する , 39 : / / V i ewport オプジェクトに挿入する。 40 : Viewport* d = new Viewport(m) : / / つぎに , それに対し , スクローラを付ける。 42 : ニ new VBox (), new HBorder, new HScroller(d)) : 43 : BOX* C 44 : / / 表示しようとするオプジェクトを World オプジェクトに挿入する。 45 : kumi->lnsert(c) : 46 : / / イベント待ち 48 : 49 : kumi->Run() :
普通は , (fset ' 1S1 (symbo ト function 'ca 「 )) のように使い , 関数の別名定義に使います。 ちなみに , symbol-function は , シンポルか ら関数スロットの値を求める関数てす。 de a 数名 [ 値 [ ュメン村 1 変数を宣言します。変数名シンポルの引 数は評価されません。評価時に変数名シン ポルに値が設定されていなければ , 指定し た値を setq のように代入します。値の既定値 は nil てす。 ドキュメントが指定されていれば , その 文字列はシンポルの属性リスト中に入れら れ , オンラインヘルプによって参照されま す。 defvar がなくても大域変数は使えますが , 後からプログラムを読むときなどに理解を 助けます。また , defva 「を使っておけば , そ のモジュールをロードしたときに , . emacs な どて設定しておいた値を再設定してしまう ことがなくなります。 make-vector 長さ初期値 べクタを新しく作って返す関数てす。 (make-vector3 nil) とすると , 長さ 3 て要素 がすべて nil のべクタがて、きます。 a 「 ef べクタインテックス位置 べクタや文字列要素を参照する関数てす。 (arefpoi2) とすると , 変数 poi に束縛されて いる配列 ( または文字列 ) の , インデックス 2 の位置にある要素を返します。インデック スは 0 オリジンてすから , この場合は 3 つ目 の要素を返します。たとえば , poi の内容が ヾ [ 0 1 2 3 4 5 ] 〃のときは 2 が返ります。 poi の内容が qabcdefg" のときは ?c, つま べクタに関する関数 60 CMAGAZINE 19 7 り 99 が返ります。 aset べクタインテックス位置値 a 「 ef と逆に , べクタや文字列の要素を更新 する関数てす。 (aset poi 2 nil) とすると , 変数 poi に束縛されている配列の , インデッ クス 2 の位置にある要素が nil になります。イ ンデックスは 0 オリジンて、すから , この場合 は 3 つ目の要素が更新されます。たとえば , poi の内容が贒 0 1 2 3 4 5 ドのときは , poi は 0 1 nil 3 4 5 ] 〃となります。 poi の内容が "abcdefg" のときに (aset poi 2 ? z) とすると , poi は "abzdefg" となりま insert 内容 関数 バッフアに関する す。 後ろにポイントを移動します。 ト位置に文字列または文字を挿入し , その とります。現在のバッフアの現在のポイン 文字列 , または文字を表す数値を引数に po intc ト位置のインデックスは , 1 オリジンて、す。 現在のポイント位置を返します。ポイン goto - cha 「インテックス 式 ... を順次評価します。この関数を出ると 引数は , 評価されないて、渡されます。 save—excursion 式 イントを移動します。 引数て、指定されたインデックス位置へポ 引数て指定された変数を , バッファロー make-loca ト valiable 変数 きの状態に戻します。 きには , ポイントとマーカーを , 入ったと カル変数にします。 関数 制御構造に関する たときにバッファローカルになる変数にし 引数て指定された変数を , 代入がなされ make-valiable-buffer-locaa 数 Emacs Lisp には , do 系の制御構文も , 関数 例外処理に関する 外名には , e 「「 0 「 , quit などがあります。 例外名て示される例外を発生します。例 signalflJ 外各値 いるようてす。 Lisp て、は , throw などを例外処理て実現して うべきだと思っていますが , 逆に , Emacs や chatch, unwind-protect などによって行 私個人としては , Lisp の例外処理は , throw Ada などの言語に採用されているものてす。 に関する機構があります。これは , CLU, Emacs Lisp には , 例外処理 ( 工ラー処理 ) 繰り返し評価します。 て , 条件が真てある ( nil て、ない ) 間 , 式 ... を す。使い方は , C や PascaI の while 文と同じ wh ile は , 引数を評価せずに受け取りま h ⅱ e 条件式 のて , そちらを使ってください は , if 文 , while 文 , and 文 , 0 「文などがある の制御構文もありません。制御構文として tagbody と go の制御構文も , block と return dition - case 変数名本体例外処 外を扱います。引数は , 評価されないて渡 本体を実行中 , signa によって発生した例
のも , 研究者たちはコンヒ。ューティングサ ービスを提供することよりも研究に関心を もっていたからて、した。最初に私が参加し たのは人間情報処理と呼ばれる研究所のグ ループて、 , そこて、は心理測定学やコンヒ。ュ ータ音楽 , そのほかさまざまな非常に興味 深いテーマを研究していました。そこから まずコンヒュテーションセンターのグルー プに移りました。なぜなら , コンピュテー ションのサービスを提供する必要があると 感じたからて、す。私はそこて、役に立っこと がて、きると思いました。 1 年ほどそのグルー プて、作業をしたころ , コンヒ。ュテーション センターがリサーチグループから分離され ました。そのとき , 私はリサーチグループ , つまりコンヒ。ュータ科学の研究にとどまる ことに決めました。そしてこのグループに よって UNIX が開発されたというわけて、す。 実は , ベル研が Multics プロジェクトから の撤退を決めたのは , 私がこれまて、経験し てきたなかて、も優れた運営決定のひとつだ と考えています。ベル研が Multics を続けて いたなら , デニス・リッチーやケン・トン プソン ( 編注 : IJN Ⅸの開発者 ) など , 多くの 人たちが多くの年月を費やして Multics を機 能させようと努力を続けていたて、しようし , 成功していたと思います。しかしそのかわ り , ベル研はミニコンピュータ革命をまっ たく経験て、きなかったと思います。 B 言語への取り組み 言語の開発自体に取り組む前にあなた が行っていたことは別として , あなたが関 与した中間的なプロジェクトはあるのでし ようか。 当時コンピュータは , データ処理 Johnson や科学計算などおもに数学的な処理に使わ れていました。テキストやシンポル的な仕 事に関しては , コンヒ。ュータはほとんど使 われていませんて、した。 ALTRAN プロジェ クトはコンビュータ上て、多項式計算を行お うとしたものてした。私たちは ALTRAN の ための実行言語として非常に移植性の高い FORTRAN の方言を使いましたが , 私たち が開発した多くの技術や , ALTRAN を移植 可能なものにするために培った多くの知識 は , 最終的には UNIX において非常に有益て、 あることがわかりました。たとえば , デニ ス・リッチーは ALTRAN コンパイラを書い ています。 実際私は , コンヒ。ュテーションセンター て、働いていたときにあったハネウェルのメ インフレームて、言語の開発に取り組み始め ました。そのときデニス・リッチーは B と呼 ばれる言語をインプリメントしていました。 私たちが使っていたハネウェルのシステム には B 向けのコンパイラがあったのて、すが , デニスが UNIX に取り組み始めたために , B は身寄りがなくなってしまいました。そこ て、彼の同意を得て , 私は B を保守することに というのも , そのとき私はハネ ウェルて、多くのコンヒ。ューティング作業を していましたし , B に組み入れたいと考えて いた特長があったからて、す。とくに私は , 当時 B にはなかった排他的 OR 演算了・が必要 て、あると考えていました。私たちは上向き の矢印をそのシンポルに決め , コンパイラ に組み入れる作業に取りかかりました。私 は , 多くのプログラミングを学ぶには徒弟 として働くことがいちばんだと信じていま すが , 私の場合 , たしかにデニスのコード を読んだり学んだりすることて、 , コンパイ リングについて非常に多くのことを学びま した。実際には排他的〇日演算子を B に組み 入れることはかなり困難て、あることがわか りました。というのも , オリジナルの B コン パイラには優先順位に基づいた奇妙な字旬 解析システムがあったからて、す。そんなと きに , 私の同僚のひとりアル・エイホが , 当時読んだいくつかの論文に排他的 OR 演算 了・を B に組み入れるよりよい方法が示唆され ていることを教えてくれました。そこて、私 はアルとの共同作業を始め , その方法につ いて学びました。その成果が YACC ( 編注 : Yet Another Compiler-Compiler の略 ) て、した。これは , 実際には初期の UNIX アプ リケーションのひとって、した。初期の YACC は B て、書かれ , インタブリタとして UNIX 上 て、作動しましたが , 後にそれが私たちのほ とんどが知っている UNIX の登場を早める結 果になるんて、す。なぜなら , それは元来ハ ネウェルシステムて、作動していたからて、す。 YACC を 生み出した環境 YACC はあなたひとりで作ったのです か。それともほかに大きく貢献した人がい るのですか。 J0hnson YACC のコードはすべて私が書き ました。しかし私が行ったことはアル・エ イホの影響を多く受けています。彼はアド バイザーて、あり , 当時私のばらばらだった 知識をまとめて , 進むべき方向を見いだす 手助けをしてくれました。理論を学びなが らプログラムを書くことは非常にエキサイ ティングて、あることがわかりました。なぜ なら , プログラムは新しい理論的な方向を 示してくれますし , 理論は私たちがプログ ラムて、て、きる新しいことを示唆してくれた からて、す。理論と実践は互いをうまく吸収 し合っていました。 当時のベル研における UN Ⅸコンピュー タ科学研究グループの環境 , つまり施設や コンピューティング環境 , 研究の雰囲気に ついて簡単に話してください。 J0hnson 最初にこのグループに参加したの は , ちょうどベル研て、 Multics プロジェクト が崩れたときだったのて、すが , 研究意欲は 非常に低下していました。ソフトウェアグ ループ全体が解散されるという噂もいくつ かありました。ベル研の経営陣が研究者の オペレーティングシステムへの取り組みを 禁止したといった , まことしやかな噂もあ りました。ベル研は MuItics のために数百 , 数千万ドルをムダにしてしまったのて、す。 実質的にベル研のすべての部門が一定の時 間を費やして MuItics に備えていました。そ Steve Johnson ポータブレ C コン督ラ P 制作者