00 C 十十クラスライプラリ概論 i を a の次の要素に進める。最終の要素ならば 0 を代入する。 a (i) ・ Base x a ( i ) は i によって指示されている要素への参照 を返す。 a. owns(i) ・ int present Pixi が a の妥当な P ⅸ値て、あれば真を返す。要 素の集まりはいつも要素を巡回して Pix に対応 する要素があるかどうかを確認しなければな らないため , この操作は比較的遅いことがよ くある。 コンテナクラスの中には次のような後ろからの巡 回をサポートしているものもある。 a.last( ) ・ Pixi i が a の最後の要素を指示するようにする。 a が 空ならば 0 を代入する。 ・ a. prev(i) i が a の前の要素を指示するようにする。前がな ければ 0 を指す。 等号演算を持った要素の集まりには以下の操作が ある。 ・ Pix j a. seek(x) 最初に出現する x のインデックスを j に代入す る。 x が a に含まれていなければ 0 を返す。 Bag クラスには以下の操作がある ( * 12 ) 。 a. seek(), Pix from = 0 ) ・ Pixj i の次に出現する x のインデックスを j に代入す る。 x が a に含まれていなければ 0 を返す。 i が 0 なら , 最初の x のインデックスを返す。 Set クラス , Bag クラス , および PQ クラスには以下 の操作がある。 a. add (x) ( 優先度つきキュー ( 待ち行 ・ Pixj 列 ) クラスでは a. enq(x)) 集まりに x を加え , その Pix 値を返す。ある項 目の Pix 値はそれが属する集まりにさらに要素 が加えられたり削除されたりして要素の実際 の移動が起こると変化することがある ( 現在の ところ , こうしたことは OXPSet クラス , OX PBag クラス , XPPQ クラス , および VOHSe t クラスて、起こる ) 。それ以外のあらゆる場合に は , ある項目の Pix 値はその位置を示す恒久的 なキーて、あると考えてよい ヘッダファイルと , C 十十から C へのインタフェイス 以下に示すファイルは , C 十十プログラマが C ライ プラリとシステムコールとを使用することがて、きる ようにするために供給されている。各ファイルの名 前と内容は近々配布が始まる GNUC ライプラリとコ ンパチプルとなるように変更されることがある。 こに示さなかったファイルは単に C ライプラリのファ イルに対応する C 十十コンパチプルなインタフェイス て、ある。 ・ values. h 組み込み型のビット数 , 最大値 , 最小値など を定義している定数が集められている。ほと んどの名前は Sun システムの v 引 ues. h の中の名 前と同一て、ある。 ・ std. h システムコールとⅱ bc. a 中の C 関数の集まりて、 ある。新しい型の定義 ( たとえばソケット構造 体 ) を取り入れることなく宣言することがて、き る関数のみが納められている。このような宣 言には , cha 「 * についての関数 ( strcmp など ) が含まれる。関数はすべてそのライプラリ名 て、宣言されているため , 安心して多重定義て、 きる。 ・ string. h 文字列操作関数のプロトタイプ宣言はく std. h > にあるのて、 , このファイルは単にそれをイ ンクルードするだけて、ある。 string. h と string s. h が異なる内容を持っていることがしばしば このようなことがなされている。 あるために ・ osfcn. h システム関数のプロトタイプはく std. h > て、宣 言されているのて、 , このファイルは単にそれ をインクルードするだけて、ある。 ・ libc. h C のライプラリ関数のプロトタイプ宣言はく s td. h > にあるのて、 , このファイルは単にそれを インクルードするだけてある。 ・ math. h ふつう libm. a にある関数のプロトタイプ宣言が あるほか , AT & T バージョンの定数と矛盾し * 12 この Bag と Set とい うのは , ある要素の多数の 集まりのことてあるただ 0 、 set は同じ要素の重複を許 さず , Bag は許すところが 違う。 特集 C + 十クラスライプラリ概論 77
す。 @fardata, @fardata? 最後の . F @Line モジュール内の現在の行 ARDATAi-•ィレクテイプ , あるい 番号を返す定義済みイクエイト。 は . FARDATA? ディレクテイプて、 インクルードファイルの中て、は , 定義されたセグメントの名前を返 インクルードファイルの先頭から す定義済みテキストマクロ。通常 , 相対な行番号を返す。マクロ内て、 このマクロは , FAR DATA または は , ソースファイルの先頭から相 対な行番号を返す。プログラマが FAR BSS と同じ。 定義したエラーの行番号を表示す @FileCur, @FileName @FileC るときに便利。 ur は , 必要な相対パス , または絶 対パスをすべて含めたソースファ @ModeI . MODELi•ィレクティ イルやインクルードファイルの名 プて、以前に定義されたメモリモデ 前を返すテキストマクロ。 @FiIeN ルに応じて Fig. 6 のような値を返す ame テキストマクロは , 現在のアセ 定義済みイクエイト。 ンプリファイルのべース名を返す。 タイニーメモリモデルとフラッ インクルードファイルの中て、は , トメモリモデルを識別することが 呼び出し側のソースファイルの名 て、きるのは @ModeI イクエイトを使 前を返す。このマクロは , ソース ったときだけ。このイクエイト は , . MODEL ディレクテイプが前 ファイルやインクルードファイル の名前が変更されたとき , 変史さ にある場合にだけ定義することが て、き , 条件っきアセンプリプロッ れたファイル名を知るために使わ Fig. 7 マクロ '@SubSt「" の構文 ク内て、よく使われる。 れる。 @SubStr(string, start [,length] ) name SUBSTR textitem, start [,length] @lnStr @InStr マクロ関数は , F @SizeStr テキスト項目の文字単 ig. 4 のような構文て、用いられ , 文 ジョンて、は 600 を返す。 MASM 5. が指す文字の右側 ( その文字を含む ) 位の長さを返すマクロ関数。 0 以前のバージョンに対しては定義 字列 <stringl> 内て、文字列 <stri @SizeStr(string) の文字をすべて返す。 @SubStr 関 ng2 > を検索し , 最初に一致した文 数は , 式演算子 ( % ) を使わないか name SIZESTR textitem されていない の構文て、使用されます。構文中て、 字列の 1 文字目の位置を返す。 < po ぎりマクロや式を展開しない <name> は一意なシンポル名 , <st @WordSize ワードのサイズを返 sition > パラメータを与えれば , そ の位置から検索が始まる。 @InStr ring> は文字列 , <textitem> は @stack スタックセグメントを含 す定義済みイクエイト。デフォル テキスト項目て、なければならない むグループの名前を返す定義済み 関数は , 式演算子 ( % ) を使わなけ トの 16 ビットモードて、は , @Wor @SizeStr 関数は式演算子 (%) れば , マクロや式を展開しない イクエイト。このイクエイトは , dSize は 2 を返す。 32 ビットセグメ を使わないかぎりマクロや式を展 先行する . MODEL ディレクテイプ 最初の 1 文字目の位置は 1 となる。く ントの 80386 / 486 プロセッサ (FLA 開しない。 0 は null 文字列を示す。 て、定義されているとおり , NEAR stringl > が見つからなければ@ln T モデルなど ) て、は , @WordSize は STACK て、は DGROUP に , FARS 4 を返す。このイクエイトは , セグ Str は 0 を返す。 メントの外部て、は , プロセッサ選 @SubStr @SubStr マクロ関数 TACK て、は STACK に展開する。 は , Fig. 7 のような構文て、用いら @ lnterface 現在の言語型および 択ディレクテイプや OPTION SE GMENT : ディレクテイプて、設定 オペレーティングシステムの型を れ , 指定された文字列をテキスト @Version 現在のアセンプラのノヾ されたデフォルトのワードサイズ 示すバイトサイズのビットフラグ 項目から取り出す。 < length > が与・ ージョン番号を示す 3 桁の数字を返 えられなければ , 関数は <start> す定義済みイクエイト。このバー を返す。 を返す定義済みイクエイト (Fig. Fig. 4 マクロ "@旧St ドの構文 @lnStr( [position] stringl , string2) name INSTR [position, ] textitem 1 , textitem2 Fig. 5 @lnterface のビット ビット 0 ー 2 ピット 7 000 予約済み 0 MS-DOS か Windows 1 OS / 2 001 C 010 SYSCALL 01 1 STDCALL 100 Pascal 1 01 FORTRAN 1 10 BASIC 1 1 1 予約済み ※ほかのビットは , 今後の使用のためにすべて予約されており , 値は定義されていません。 Fig. 6 @ Model' ' が返す値 メモリモテル タイニ 1 スモール 2 コンノヾクト 3 ミディアム 4 ラージ 5 ヒュージ 6 フラット 7 lnformation from Compiler Makers 155
のシエネリックコレクションにはビット配 列 , 単方向リスト , 双方リスト , スタック , キュー , べクタ ( 配列 ) , ソートされたべク タが用意されている。ジェネリックコレク ションクラスの一覧を Table 4 に , GSlist (type) のメンバ関数を Fig. 9 に示す。単方向 リストに必要なほとんどの機能を備えてい るといっていいて、あろう。 GStack ( type ) を 使った簡単なサンカレコーデンングを List 13 Sma 肚引 k - ⅱ ke コレクションクラス TooIs. h 十十最大の売りが , Smalltalk-Ii ke コレクションクラスて、ある。その一覧と クラス階層を Table 5 , Fig. 10 に示す。 コレクションはすべて RWCollectabIe の 派生クラスて、あり , RM ℃ ollectable の派生 クラスをコレクションの要素とする。した がって , コレクションの要素が , さらにコ レクションて、あってもかまわないことにな る。たとえば単方向リストの配列とか , ス タックに積まれた各要素が二進木て、あると いった複雑なデータ構造が可能て、ある。 sm alltalk-like コレクションクラスの項点に立 つ抽象べースクラス RWCollectabIe および コレクションの抽象べースクラス RWC011e ction の主要なメンバ関数を Fig. 11 , Fig. 1 2 に示す。 コレクションの要素となるクラスは RWC ollectable の派生クラスて、なくてはならず , に示す。 Fig. 9 GS ⅱ st ( type ) のおもなメンバ関数 ・ type * append(type* a) リストの末尾に a を接続する ・ void apply(void ( * (p) (type * , void * ) , void* ) リストの各要素に対し関数 ap を適用する ・ type* & at(int i) i 番目の要素を返す ・ void clear( ) リストを空にする リスト中から e と同一の要素を探す ・ type * findReference(const type * e) const リスト中から要素を探す const VOid * ) , const VOid * ) const ・ type* find(RWBooIean (*tst) (const type * , リスト中の要素数を返す ・ unsigned entries( ) const e と同一 ( 同じアドレス ) の要素を探し , 見つかれば TRUE を返す ・ RWBoolean containsReference(const type * e) const tst は条件を満たせば TRUE を返す関数 リスト中から要素を探し , 見つかれは丁 RUE を返す const VOid * ) , const VOid * ) const ・ RWBooIean contains(RWBoolean ( * tst) (const type * , ・ type* first( ) const 先頭の要素を返す ・ type * get( ) 先頭の要素を抜き取る ・ type * insert(type* a) リストの末尾に a を接続する ・ type* insertAfter(int i, type * i 番目の要素の次に a を接続する ・ RWBooIean isEmpty( ) const リストが空ならは〒 R まを返す ・ type* last( ) const 末尾の要素を返す a) ・ unsigned occurrencesOf(RWBoolean ( * tst) (const type * , const VOid * ) , const VOid * ) const 条件を満たす要素の数を返す ・ unsigned occurrencesOfRefference (const type * e) e と同一要素の数を返す ・ type* prepend(type * a) リストの先頭に a を接続する ・ type * remove (RWBoolean ( * tst) (const type * , const VOid * ) , const VOid * ) 条件を満たす要素をリストから抜き取る ・ type * removeReference (const type * e) e と同一の要素をリストから抜き取る 60 C MAGAZINE 1 2 7 Fig. 10 Sm 訓 ta 賑ヨ ike コレクションのクラス階層 RWCollectable RWCo ction ( 抽象べースクラス ) RWBinaryTree RWBTree RWBTreeDictionary RWBag RWSequenceabIe( 抽象べースクラス ) RWDlistCollectables RWOrdered RWSortedVector RWSlistCollectabIes RWSlistCollectablesQueue RWSlistCoIIectablesStack RWSet に RWIdentitySet RWHashDictionary L—RWldentityDictionary Fig. 1 1 RWC ectab 厄のおもなメンバ関数 ・ virtual RWCoIIectabIe テストラクタ ・ virtual unsigned binaryStoreSize( ) const バイナリファイルへセープする際に必要なノヾイト数を返す ・ virtualint compa 「 eTo(const RWCollectable * c) const *this と * c を比較し , 負 / 0 / 正の値を返す ・ⅵ u 引 unsigned hash( ) const ハッシュ値を返す ・ virtual ClasslD isA( ) const クラスにユニークな旧 ( unsigned ) を返す ・ virtual RWBoolean isEqual(const RWCollectable * c) const *this と * c が等しければ TRUE を返す ・ virtual RWCoIIectable * newSpecies( ) const インスタンスを new して , そのポインタを返す ・ virtual void 「 estoreGuts(RWFile&) virtual void restoreGuts(RWvistream&) インスタンスの内容をファイル / ストリームから読み込む ・ virtual void saveGuts(RWFiIe&) const ⅵ u 引 VOid saveGuts(RWvostream&) const インスタンスの内容をファイル / ストリームに書き出す ・ static RWCollectable * 「 estoreFrom (RWFiIe&) static RWCollectable * restoreFrom (RWvistream&) ファイル / ストリームの内容にしたがってインスタンスを構築する ・ void saveOn (RWFiIe&) const VOid saveOn (RWvostream&) const 再構築可能な形式でファイル / ストリームに書き出す ・ unsigned shallowStoreSize( ) const saveOn(File&) に必要なバイト数を返す
し , て、きるだけ融通が利くように ほとんどのクラ スが、、はめこみアセンプリコード〃手続きを持ってい る。これによってプログラマは時間的 , 空間的 , そ して評価のストラテジを完全にコントロールするこ とがてきるようになる。この手続きはほとんどの場 合 , ふたつの const のソース引数とひとつのデスティ ネーション引数とを持った、、 3 ーアドレス〃手続きと呼 ばれるものて、ある。この手続きは適当な動作を行っ たあと , 結果をデスティネーションに書き込む ( 古い 値の上に重ね書きされることもあり得る ) 。手続きは 高速て、安全て、あるように設計されている。とくに 別名参照は常に正しくなされるため , たとえば add (), x, x) ; などというコードも完全にうまく働く ( これらの手続きの名前はクラスといっしょに並べら れている ) 。 たとえば ,lnteger の式 a = (b ー a) * -(d / c) ; を考えてみる。この式は以下のようにコンパイルさ ように自分て、直すことがて、きる。 しかし , 手動による賢い最適化によって , 以下の t3 = -t2 ; lnteger t4=tI * t3 ; lnteger tl=b-a ; lnteger t2=d/c ; lnteger れる。 a=t4 ; 76 C MAGAZINE 1992 7 用するよりはるかに明解て、ある。コードを正しく動 演算子は非常に快適て、あり , 手続き的なコードを使 ガイドラインの最後に付け加えておく。多重定義 ることがて、きる。 return ; } とす er&a) return r(a) { 「十 = a , 必要はない。上記の例て、は , lntegerf(constlnteg にインスタンスを作成し , 戻り値としてコヒ。ーする 作することを許す。したがって , 関数内部て、局所的 名前つき戻り値は , 返されたオプジェクトを直接操 戻り値 (named return value) を使用する方法がある。 ーされなければならない。 GNU C 十十て、は名前つき 出した側が使えるようになる前に関数の外部にコビ 様なムダなコビーを作ることになる。戻り値 r は呼び この関数が ( a f(a) ; のように ) 呼ばれると , 同 「十 = a ; retu 「 n 「 a lnteger f(const lnteger&a) { lnteger 「 を書くとしよう。 成して返す関数を作るときにも生じる。以下の関数 これに関連した現象はある型のインスタンスを作 作するようにし , 正しいことを確認したそのあとで 式の形式のコードを手続き的なコードに直して高速 化を図るのはよいことて、あるといえる。 擬似インデックス (pseudo-indexes) 便利なクラスには要素のコンテナとして動作する ものが多い。コンテナからこれらの要素をアクセス するテクニックはクラスによってさまざまて、ある。 GNU C 十十ライプラリて、は , Pix と呼ばれる擬似イ ンデックスを使うことによってクラス間のアクセス メソッドが部分的にて、はあるが標準化されている。 Pix の働きは , あるいはインデックスのようて、もあ り , あるいはポインタのようて、もある ( 内部的にはた だの void * ポインタて、ある ) 。 Pix はクラスによって 要素へのアクセスに翻訳される一種の「キー」て、ある。 実際には P ⅸは何らかの内部記憶セルへのポインタて、、 ある。コンテナは要素を取り出す際にこのポインタ を使用する。 ューザは Pix の要素の集まりを巡回したり閲覧した りする際に配列のインデックスと同様の方法を用い ることがて、きる。しかし , P ⅸは 0 が不適切なものとし て扱われているという点においてポインタに類似し ており , プログラマが値の妥当性を確認せずに不適 切な Pix を使用して存在しない要素にアクセスしよう とする場合がある , というかぎりて、は安全なものと はいえない 一般的にいえば , コンテナへの破壊的な変更を行 っている最中に巡回を行うのは決してよいことて、は ない。典型的な応用例は以下のイディオムを用いた コードて、あろう。 a. first( ) ・ fo 「 (Pix i use(a(i)) ・ 0 ; a. next(i)) このコードはあるコンテナ a と関数 use のためのコ ードて、ある。 Pix による使用をサポートしているクラスは常に以 こて、はコン 下のメソッドを持っている。ただし , テナ a は型 Base の要素を持つものとする。 a. first ( ) ・ Pix i i が a の最初の要素を指示するようにする。コン テナが空ならば 0 を代入する。 ・ a. next(i)
・・ nt even(long ⅵ・ x が偶数ならば真を返す。 ・ int odd(long y) ・ x が奇数ならば真を返す。 * 13 HUGE に注意せよ ! ! HUGE の値は適切か ? HUGE-HUGE はどうなる か ? HUGE ー HUGE> 0 は 0 か 1 か ? ふつうの人は 関係ない * 14 overload 宣言はす て、に時に遅れの構造て、ある。 AT&T C 十十 2.0 て、も g 十十 (djgpp) て、も , 関数の 多重定義のために over load 宣言は必要ない。いま となっては , この言も 時代遅れ二いまて、は math. h に overload 旦言は存在し ない。ちなみに overload 宣 言は行ってもかまわないが , 行うと overload という識 別子はもう使えない。 * 15 デフォルトの new 演 算子の宣言は void * new (size t) ; てある。ここてい う 2 引数バーションというの は第 2 引数が void * て、ある 代替の旦言の旦言て、あるが , これに対し , void* new .. ) ; というのも (size し 許されている。 * 16 この GNUC 十十ラ イプラリては , プーリアン カリ挙とされているが , れは C 十十てはよくない。と いうのも多くの人は , プー リアンに対して ! などの論理 演算とかを行いたいだろう が , 現在の C 十十はそれを許 さない。したがって , AT& T C 十十との互換性を考え た場合 , プーリアンには , typedef unsigned int boolean , const unsigned int true = 1 : const unsigned int false = 0 : を使うべきてある。 78 C MAGAZINE 1992 7 ないと思われる定数が # define によって定義さ れている。 HUGE の値は使用前に確認してお いたほうがよい ( * 13 ) 。数学関数はふつう多重 定義されるのて、 , その宣言にはすべて overlo ・ stdio. h ad 力すついている ( * 14 ) f の宣言は使用前に確認しておいたほうがよ ロトタイプ宣言がある。 BUFS にの値と iobu えば getc), 日 LE * を扱うⅱ bc. a 中の関数のプ 日 LE ( iobuf) とふつうあるようなマクロ ( たと ・ assert. h assert マクロの C 十十 / ヾージョンて、ある。 gener ・ ic. h AT&T CC の generic. h と類似している。 文字列連結マクロの定義がある。機能的には ジェネリッククラスを生成するときに便利な new. ・ void clearbit(long& x, long b) ・ ていないことは注意しておくべきて、ある。 a 版て、ある intabs(int) はインライン宣言され これは abs のインライン版て、ある。標準の libc. ・ long abs(long x) : double abs(double x) ; 義のほかに , 以下にあげるものがある。 g 十十のエラーハンドリング関数へのポインタの型定 TR U E と FALS E のような有用な列挙型 ( * 16 ) や , lib インラインて、ないものもある。そして , それらには 関数がある。それらにはインラインのものもあるし , ている . cc ファイルには多数の便利なユーティリティ builtin. h ファイルとそれに対応する実装が記述され ユーティリティ関数 組み込み型の演算に関する ( * 15 ) 工ラーハンドラの宣言がある。 大域演算子 new のデフォルト版および 2 引数版 ・ int testbit(long x, long b) ・ て、ある。 x の b 番目のビットをセットする。インライン ・ void setbit(long& x, long b) ; て、ある。 x の b 番目のビットをクリアする。インライン x の b 番目のビットを返す。インラインて、あ インラインて、ある。 インラインて、ある。 ・・ nt sign(long x) ・ int sign (double x) ・ x が負ならば一 1 , 0 ならば 0 , 正ならば 1 を返 す。インラインて、ある。 ・ long gcd(long x, long y) ; x と y の最大公約数を返す。 ・ long lcm(long x, long y) ・ x と y の最小公倍数を返す。 ・ long lg(long x) ・ 2 を底とする x の対数の小数部分を切り捨てた 整数値を返す。 ・ long pow(long x, long y) ; double pow (double x, long y) ; 計算量が O ( 1 。 gy ) て、ある、、ロシア農民法クを繰 り返し用いて , x の整数 y 乗を求める。 ・ long sqr(long x) ; doublesqr(doublex) ; x の平方を返す。インラインて、ある。 ・ long sqrt(long y) ・ x の平方根の小数部分を切り捨てた値を返す。 ・ unsigned int hashpjw(const char * s) ・ null て、終わる char * 文字列のハッシュ関数値を 返す。ハッシュ関数は Aho , Sethi, & Ullm an, p. 436 に記述されている方法を用いる。 ・ unsigned int multiplicativehash (int x) ・ 整数値のためのハッシュ関数値を返す。具体 的には , x と黄金率と p 。 w ( 2 , 32 ) との積を返 す。詳しくは Knuth, V01 3 , p 508 を見るこ ・ unstgned int foldhash (double x) ・ 倍精度実数値のためのハッシュ関数値を返す。 具体的には , x を 2 ワードに切り , それらの排 他的論理和を整数とみなして返す。 ・ double start timer( ) プロセス時間をスタートさせる。 ・ double return elapsed time(double last t ime) last time からのプロセスの経過時間を返す。 last time が 0 ならば , start timer が呼ばれてか
= = ロ ll(l GCCWorld 第 9 回システム依存ライフラリ 安田英之 ( 株 ) プロシード 今回は , システム依存ライプラリの解説と 98 バッチの H バ ージョンで追加された機能を実際にプログラム上でどの ように利用できるかを実例で紹介します。システム依存 ライプラリはライプラリの解説の最後となります。 成功したら 0 を返し , 失敗したら errno に ファイルの存在をチェック ンステム依ライプラリ ENOTDIR を設定して , ー 1 を返します。 mode = 2 のとき 書き込み可能かをチェック mkdir. s libsrc/c/sys のシステム依存ライプラリに 可能なら 0 , 不可能ならば一 1 を返す mode = 2 て、一 1 を返す場合は , errno に EA int mkdir(const char * path) ・ は , アセンプラて、直接書かれたソースがた パス名 path のディレクトリを作成しま CCES が設定されます。 くさん入っていますが , これらはほとんど す。成功したら 0 , 失敗したら一 1 を返しま 内部て、 DOS のファンクション 43h を呼び出 DOS のシステムコールや g032 のサポートル ーチン turbo assist を呼ぶだけて、 , それほど しています。 す。 複雑な処理を行っているわけて、はありませ brk. s rmdir. S ん。 アプリケーションから直接使うことを想 int rmdir(const char *path) ・ void *brk(void *address) ・ メモリプロックの最終アドレスを addres パス名 path のディレクトリを消去しま 定していない関数 , および UNIX との互換性 s に変更します。変更前の最終アドレスを返 す。成功したら 0 , 失敗したら一 1 を返しま のためにのみ用意されていて意味のある動 します。 す。 作を行わない関数 , 具体的には次の関数に ついては , 説明を省略します。 sbrk. s creat. S crlf2nl. c chown. C chmod. c void *sbrk(int incr) ・ int creat(const char *name, fchmod. c fsync. h errno. S メモリプロックのサイズを相対指定によ unsigned long int mode) ・ getpid. c signal. c getdtabl. c パス名 name のファイルを作成します。 U って変更します。 incr には , 増減量をバイト utime. C umask. C turbO. s, NIX て、は作成するファイルのモードを mod 単位て、指定します。変更前の最終アドレス utimes. C e に指定しますが , djgcc て、は mode は無視さ を返します。 access. S れ , 常に読み書き可能なファイルが作成さ chdir. s れます。 int access (const char * filename, 成功したら作成したファイルのファイル int mode) ・ int chdir(const char *path) ・ ハンドル , 失敗したら一 1 を返します。 filename という名前のファイルの属性を カレントディレクトリを path に変更しま turbo assist の 1 番を呼び出すことによっ 調べます。 mode の値によって , す。 DOS のファンクション 3bh を呼び出す ことによって実現されています。 て実現されています。 mode=0 のとき 128 C MAGAZINE 1992 7
Fig. 11 に示す仮想関数を必要に応じて再定 義しなければならない たとえば RWBinaryTree ( 二進木 ) や RW SortedVector ( ソートされた配列 ) の要素と するなら compareT0 ( ) を , RWSet( 重複を 許さない集合 ) や RWHashDictionary ( , 、ツ シュ表による辞書 ) の要素とするなら hash ( ) , isEqual ( ) を , さらにファイルに対しての 書き込み / 読み出しを行いたいなら isA ( ) , saveGuts ( ) , restoreGuts ( ) をそれぞれ再 定義する。 要素の性質によるコレクションの分類を Fig. 13 に示す。 SmaIltaIk-like コレクションのひとつ , R WBinaryTree を使った簡単な日記帳プログ ラム diary を List 14 に示す。日付とその日の 出来事を格納するクラス DiaryRecord を RW CoIlectable から派生し , RWBinaryTree の 要素として管理する 0DiaryRecord の比較関 数 compareTo ( ) は日付クラス RWDate の比 較関数を呼び出しているのて、 , RWBinary Tree には日付順に格納される。 プジェクトの save と「 estore ℃ ollectable 族 ( もちろん RWC011ecti0 n 族も含む ) はファイルに対して書き込みと [ なし ] →キーによる検索 読み出しを行える。読み出しの際は , 空の インスタンスを new し , その内容をファイル から読み出す。このとき T001S. h 十十て、は巧 妙なからくりて、ポインタの接続を管理して いる。 Fig. 14 をご覧いただきたい。たとえ ば単方向リストをファイルに save すること を考えてみる。 わない。これらの要素を単純に save する と , restore したときに元の構造とは異なる ものになってしまう。 TooIs. h 十十は , このような重複するオプ ジェクトを save するときにはオプジェクト 情報を基に復元する。また , コレクション 内の要素をすべて delete する際も同様の機構 によって , 重複する要素を何度も delete しな いようになっている。 格納された要素の数が 0 ならは〒 RUE を返す ・ virtual RWBoolean isEmpty( ) const = 0 c を要素として格納する ・ virutal RWCollectable* insert(R\A ℃ ollectable* c) ニ 0 * c と等しい要素を探す ・ virtual void 「 emoveAndDestroy(const RWCollectable * c) = 0 * c と等しい要素を取り除く ( de 厄 te しない ) ・ⅵ u 引 RWCollectable * 「 emove (const RVi ℃ ollectable * c) : 0 * c と等しい要素の数を返す ・ virtual unsigned occurencesOf(const RWCollectable * c) const : 0 00 C 十十クラスライプラリ概論 Fig. 12 RWCollection のおもなメンノヾ関数 ・ virtual void apply(void (*f) ()W ℃ ollectable* , void* ),void * ) ニ 0 各要素に対して関数 f を適用する ・ RWBag asBag( ) const ・ RWSet asSet( ) const ・ RWOrdered asOrderedColIection ( ) const ・ RWBinaryTree asSortedCollection( ) const RWBag/RWSet/RWOrdered/RWBinaryTree に変換する ・ⅵ u 引 void clear( ) : 0 すべての要素を取り除く (delete しない ) ・ virtual void cIearAndDestroy( ) すべての要素を delete する ・ virutal RWBoolean contains(const RWCollectable * c) const = 0 * c と等しい要素があれは丁 RUE を返す ・ virtual unsigned entries( ) const : 0 格納されている要素の数を返す ・ⅵ u 引 RWCoIIectable * find (const RWCollectable * c) const : 0 Fig. 順序性 13 要素の性質によるコレクションの分類 * c と等しい要素を delete する [ 行わない ] 〔なし ] →要素の挿入 [ 遅い ] [ 速い ] [ 行う ] →要素の一致条件 [ 行わない ] →要素の第複 TO 団 s. h 十十のス、リム [ アドレスが等しい ] [ 内容か等しい ] [ 許す ] [ 許さない ] 一要素の一致条件 RWBTree, RWBinaryT 「 ee RWOrdered RWSlistCollectables, RWDlistCollectables RWIdentityDictionary RVVHashDictionary RWBag [ アドレスが等しい ] → RWIdentitySet [ 内容が等しい ] ーー→ RWSet T001S. h 十十には , オプジェクトの save/ restore のために 2 種類のストリーム , バイナ リストリーム (RWbistream/RWbostream) postream ) が用意されている。通常は高速て、 コンパクトなバイナリストリームを用いる が , ポータブルストリームを使えば , OS や マシンに依存しない save/restore が可能て、あ る。たとえば DOS 上て、 save したファイルを UNIX 上て、 restore て、きる。 DOS と UNIX の 間て、オプジェクトのやり取りがてきるわけ て、ある。 MS-Windows て、は DDE や Clipboa rd を介したアプリケーシ . ョン間て、のオプジ ェクトの受け渡しもサポートしている。 実行コドサイズ 一般に C 十十て、書かれたプログラムは C て 書かれたものに比べ , 実行コードサイズが 特集 C + + クラスライプラリ概論 61
ズからなる構造体て、 , BSD 系 UNIX のカー ネル内部のデータ転送などに使われます。 成功したときは実際に読み込めたバイト 数 , 失敗したときは一 1 を返します。 writev. C unsigned long readv (int handle, struct iovec * iOV, int count) 成功したときは実際に書き込めたバイト handle に書き込みます。 iov の指す count 個の I / O べクタをハンドル struct stat * buffer) ・ int stat(const char * path, stat. s 数 , 失敗したときは一 1 を返します。 130 C MAGAZINE 1992 7 size バイトに切り詰めます。 ハンドル handle が指すファイルの長さを unsigned long size) ・ void ftruncate (int handle, ftruncat. c トに切り詰めます。 パス名 * path のファイルの長さを size バイ unsigned long size) ・ void truncate(const char * path, truncate. C て実現されています。 turbo assist の 3 番を呼び出すことによっ こと以外 , stat( ) と同様て、す。 ファイル名て、はなくハンドルを指定する struct stat * buffer) ・ int fstat (int handle, fstat. s ものは TabIe 2 のとおりて、す。 *buffer の各フィールドの中て、意味のある て実現されています。 turbo assist の 6 番を呼び出すことによっ す構造体に読み込みます。 パス名 path のファイルの情報を buffer が指 getpages. c int getpagesize(void) ・ 仮想記憶のべージのサイズを返します。 常に 4096 て、す。 getrusage. C int getrusage(int whO, struct rusage * rusage) ・ 初めて getrusage を呼び出した時刻から現 在まて、にかかった時間を rusage ー > ru utim e に格納します。 who は無視されます。 gettimeo. s gettimeofday (struct timeval * tv, struct timezone * tz) 現在の時刻を tv の指す構造体へ , タイムゾ ーン情報を tz の指す構造体へ格納します。 t v または tz として NULL を与えると , その構 造体への代入が省略されます。 turbo assis t の 4 番を呼び出すことによって実現されてい settimeo. S ます。 べ , デバイスの場合は 1 , 通常のファイルの handle がデバイスて、あるかどうかを調 int isatty (handle) ・ isatty. s クトリのパス名を格納し , buf を返します。 buf が指す領域に現在のワーキングディレ int getwd (char * buf) ; getwd. s 実現されています。 turbo assist の 5 番を呼び出すことによって と , その構造体からの設定が省略されます。 定します。 tv または tz として NULL を与える ーン情報を tz の指す構造体から読み込んて、設 現在の時刻を tv の指す構造体に , タイムゾ const struct timezone * tz) settimeofday (const struct timeval * tv, 場合は 0 を返します。 link. s int link(const char * 0 旧 , const char * new) ・ パス名 01d のファイルの名前を new に変更 します。 01d と new とて、ディレクトリは異な っていてもかまいませんが , ドライプは同 じて、なければなりません。また , new という 名前のファイルがすて、に存在していると工 ラーになります。成功したら 0 , 失敗したら ー 1 を返します。 rename.s int rename(const char * 0 旧 , const char * new) ・ link( ) と同様て、すが , new という名前の ファイルがあればあらかじめ消してから名 int setjmp(jmp buf j) ・ setjmp. s 功したら 0 , 失敗したら一 1 を返します。 パス名 path のファイルを消去します。成 int unlink(const char *path) ・ unlink. s 前の変更を行います。 long offset, long lseek (int handle, lseek. s として返されます。 帰します。復帰時に , val が setjmp 関数の値 setjmp によって保存された実行環境 j を復 void longjmp(jmp buf j, int val) ・ longjmp. s ます。 て、引数に指定した値が setjmp( ) の値となり 時点から実行が再開されます。 longjmp() 対して longjmp を実行すると , この setjmp の 実行環境を j に保存します。あとて、この j に
uf および f ⅱ buf を呼び出す。 setbuf は連続していないバイナリ入出力を行う場 合にバッファリングを中止するために使用される。 raw は setbuf(IONBF) と同義て、ある。 f. 「 aw ( ) を実 行した後は , システムの「 ead , w 「 ite などの代わりに 標準入出力関数を使うことによるオーバヘッドはほ とんどなくなる。さらには , システムコールとの混 合操作においても完全に互換性がある ( たとえ XIsee k(). filedesc(), 0, 0 ) ) 。 F ⅱ e と入出力のシステムコ ールとの混合は決して推奨される使用法て、はないが , このテクニックを使用すれば , ファイルディスクリ プタ操作のために作成された関数およびライプラリ と FiIe クラスとを組み合わせて使うこともて、きる。 s etbuf はコンストラクタあるいはオープンの後 , あら ゆる入出力の前に多くとも 1 回だけ呼ぶべきて、ある。 ファイルステータス ファイルのステータスを管理する方法がいくつか ある。 F ⅱ e がアクセス可能かどうかは is open(), 「 eada ble ( ) , および writable ( ) て、調べることがて、きる。 i s_open( ) は File が使用可能な物理ファイルに対応づ けられているならば真を返す。「 eadable() は File が 読み込み可能 ( 読み込み用にオープンされ , かっ fai 1 ステートて、ない ) ならば真を返し , writable ( ) は FiI e が書き込み可能ならば真を返す。 F ⅱ e の操作はふたつの手段を用いてそのステータス を返す。ひとつは真か偽かという論理的な状態て、表 される。もうひとつは標準入出力関数とシステム関 数からの戻り値て、 , 真偽のフラグて、はなく意味のあ る整数値がクラス内変数に格納されており , iocoun t ( ) て、取得することがて、きるにの値を取得すること には意義がある。たとえば read( ) 関数て、実際に読み 込まれた要素の数を得ることがて、きる ) 。 rdstate( ) の動作は AT & T の入出力ストリームクラ スと同様て、あるが , Stroustrup の本の 238ページにあ る記述とは異なっている。すなわち , この関数は e of と fail, bad のビット論理和を返し , 必ずしもい ずれかの値を返すとはかぎらない。 eof ( ) , fail ( ) , bad ( ) および good ( ) を用いてそれぞれのビットの状 態を確認することがて、きる。 入力操作が希望どおりのデータを読み込めなかっ 82 C MAGAZINE 1992 7 た場合などの操作失敗時には fa ⅱがセットされる。ま た , Unix のあらゆる入出力において行われているよ うに , ファイルの末端に達したために入力操作が失 敗したときにのみ eof がセットされる。したがっ て , eof は最後に読み込みに成功した直後にセット されるわけて、はなく , さらに読み込みをしようとし てはじめてセットされる。それゆえに入力操作て、は fail と eof はほばいつも同時に真となる。 bad はファ イルに対応づけられていないときにセットされるほ か , 入力の失敗を知らせるためにアプリケーション によってセットすることもて、きる。 good は 0 に定義 されており , 操作に成功したときに rdstate() が返す 値て、ある。 ステートは clea 「 ( 利 ag ) を用いて変更することがて、 きる。ただし , この関数は clear という名前にもかか わらず , flag に対応するステート値をセットするもの て、ある。引数のない clear ( ) はステートを good にリ セットする ofailif(int cond) は cond が真て、あった場 合にのみステートを fail にする。 コンストラクタ内て、 , あるいはファイルのオープ ン時にエラーが生起した場合には er 「 or 関数が呼び出 される。 e 「 ror はシステムのエラーて、あれば F ⅱ e erro 「 handler( メンバて、はなく大域変数て、ある ) の指すェ ラーハンドリング関数を呼び出す。この変数の値は 再定義することがて、きる。 er 「 or は現在のシステムエ ラーが実際に失敗に寄 - 与しているのかどうかを判断 て、きないのて、 , まちがったメッセージを表示するこ ともあるかもしれない 二つのエラーハンドラが定義されている。デフォ ルトの verbose FiIe er 「 0 「 han 引 e 「はシステム関数 p er 「 or を呼び出して対応するエラーメッセージを標準 工ラー出力に書き込み , リターンする。 quiet File er 「 0 「 hand 厄 r は何もせずにリターンする。 fatal Fil e e 「「 0 「 han 引 er はエラーを表示して実行を停止す る。これらのハンドラ , あるいはユーザが定義する 工ラーハンドラの中から set file er 「 0 「 handler 関数 ( メンバて、はない ) によって選択することがて、きる。 あらゆる読み書き操作は論理的失敗も物理的失敗 も fail をセットすることによって知らせる。ステート が fail か bad になると , それ以降の操作はプロック される。論理的失敗の後も物理的失敗の後も入出力 処理を継続したいならば , プログラマは明示的に cle
00 C 十十クラスライプラリ概論 ている。ソースファイル malloc. c に設計と実装の詳 らの経過時間を返す。まだ start time が呼ばれ こて、は , ほとんどのシステ ていなければ , ー 1 を返す。 細が記述されている。 以下に示す型変換関数も供給されている。オプジ ムに組みこまれている malloc ルーチンとのユーザに ェクトを char * 文字列に変換する関数は呼び出しの 見える範囲て、の主要な違いを述べる。 たびに再利用される領域へのポインタを返す。した ①これらのルーチンは解放された領域の内容を重ね がって , これらは型変換関数が再度呼び出されるま 書きする ( * 17 ) 。つまり , どのような場合にも , de て、の間だけ妥当な結果を保持している。 lete されたオプジェクトを使用することは決して許 ・ char* itoa(long x, int base されないということて、ある。もしそのようなこと 10 , int w idth をしたならば , 致命的工ラーに陥るか , あるいは x をケえられた基数を用いた ASCII コード表現 malloc, free, realloc がて、たらめな abort を行うか のいずれかになるだろう。 の char * 文字列に変換して返す。表現が指定 ②これらのルーチンは同じサイズのオプジェクトを した幅より小さい領域しか用いなかった場合 大量に確保したり解放した場合によく動作する傾 には先頭が空白て、埋められる。 向がある。そのような場合には , ユーザが自分て、 ・ char * dtoa (double x, char cvt='g', int 特別な割り当て機構を作成するのは意味がないと width=0, int prec=6) ・ x を printf て、用いられるようなフォーマット様 いうことがわかるだろう。 式て、 ASCII 表現の char * 文字列に変換して返 ③ライプラリて、は , トップレベルの ope 「 ato 「 new ( ) す。各オプション引数 cvt の値が printf の g, f, は malloc を呼び , また ope 「 at0 「 delete ( ) は free を e 形式の引数に対応する。たとえば ,printf("% 呼ぶようになっている。もちろん , ューザが C 十十 f10.2 " , x) に対応するのは dtoa ( x , 'f', 10 , プログラム中て、ライプラリ版に優先する独自の演 2 ) て、ある。 算子を作成することによってこれらの定義を無効 ・ char* hex(long x, int width にすることがて、きる。しかし , そのときには ope 「 16 を基数として itoa を呼ぶ。 atornew( ) と operatordelete( ) の両方を定義し ・ char* oct(long x, int width なければならない 8 を基数として itoa を呼ぶ。 ④これらのルーチンは , malloc のいくつかの版て、は ・ char* dec(long x, int width 実装されている , 変な慣習 (oddconvention), す なわち free したポインタを「 e 訓 oc て、きるという機 10 を基数として itoa を呼ぶ。 ・ char* form (const char* fmt … ) ・ 能をサポートしていない なえられたフォーマットと引数て、 sp 「 intf を呼 ⑤ライプラリて、は , 自動的に f 「 ee されたポインタのチ ぶ。 ェックを行って , ユーザが図らずも割り当てられ ・ char* chr(char (h) ・ た領域を越えて書き込んて、いないかどうかを調べ ch を 1 文字の文字列に変換する。 て 0 、る。 = の方法 0 = よて一正な書き込みと判断 ファイル Maxima. h には , 組み込み型の MAX と M されることがしばしばあるカ , そのときは致命的 ー N が記述されている。ファイル compa 「 e. h には , 組 工ラーを発生する。 み込み型の compare(), y ) が記述されている。これ ⑥関数 m 訓 oc usable size(void* p) は p を実際に らは第 1 引数が第 2 引数よりも小さい場合には負値を 割り当てられたバイト数を返す。適切なポインタ 返し , 等しければ 0 を返し , 大きければ正値を返す。 ( たとえば m 訓 oc あるいは re 訓 oc され , かつまだ f * 17 一度呆された領域 は決して解放しないという ree されていないポインタ ) を渡すと要求したサイ 動的記憶割り当てのための 実装もよく使われる。プロ グラムが , 少しの記憶領域 ズかそれより大きい数が返ってくる。そして , そ ライプラリ基本関数 を何度となく要求し , かっ れ以外のときは 0 が返る。不幸なことて、はあるが , 滅多に解放しないという条 件を考慮すれば , この実装 libg 十十に含まれている m 訓 oc , free, 「 e 訓 oc は , 0 て、ないからといってエラーがないと絶対完全にい も速度もメモリの使用効率 C 十十アプリケーションて、使いやすいように設計され も十分優れている。 いきれるわけて、はない。当該小領域がそこては f 「 e 特集 C 十十クラスライプラリ概論 79