参照 - みる会図書館


検索対象: 月刊 C MAGAZINE 1992年7月号
66件見つかりました。

1. 月刊 C MAGAZINE 1992年7月号

りそうて、す。別の見方もて、きます。オプジ ェクト指向言語のトレンドは変数は宣言・ 定義なして、使えるということて、すが , C 十十 のこの方法はうまい折衷案と呼べなくもあ りません。 こいつの説明をするのは一苦 ああ参照。 労て、す。というのも , 参照の本当のご利益 はクラスとともにやってくるものなのて、 さて「参照」を一言て、いい表すなら , 「既存 の変数に対する別名」て、す ( List 4 ) 。て、す が , この短い文だけて、説明足れりとするの はあまりにも舌足らすて、す。かといって , 今後の文法にも通じることて、すが枝葉末節 こだわって大局を見失っては元も子もあ りません。て、すから , 参照について興味の ある読者諸兄は , 「 T ん eC 十十 og % 4 襯 襯 / 〃 g ん〃 guag Second E イ〃 / 0 がを 参照してください : -PO という冗談はさて おき , なぜ参照なんてものカ℃十十に存在す というわけて、 るのか。なくてはならない コラム C 十十の fo 「文 C 十十では , 翫文の定義が拡張されていま す。 く C の場合 > fo 「 ( 式 : 式 ; 式 ; ) 文 三つある式がそれぞれ「最初に一度だけ実 行される」「ループの前に実行されて偽なら ループを抜ける」「ループの後に呼び出され る」ということはいわずもがな , ですね。 く C 十十の場合 > fo 「 ( fo 「初期化文式 1 ; 式 2 ) 文 となっています。 f0 「初期化文とは , 式文ま たは宣言文です。つまり , f0 「初期化文に は , 通常の「式 ; 」という文または「 int a ; 」 などの宣言文が書けるわけです。なお , fo 「 初期化文で定義した変数は , fo 「文の中だけ 、でなく , 宣言以降の , fo 「文を含むプロック 中で有効です。 88 C MAGAZINE 1992 7 もありません。仮に参照がないとしても , ポインタを使えばそのほとんどの機能は実 現可能て、す。 て、は , どんな理由があってわざわざ参照 などというものを作ったのカ 「参照」は , 既存の変数に対する別名て、あ ると書きました。この字面だけを単純に追 うとポインタの働きによく似ていますが , ひとつだけ決定的に異なることがあります。 それは , 「参照は変数の実体を指すことが保 証される」ということて、す。参照は , 定義さ れると同時に , 実体を指すよう初期化され なければなりません。ポインタには , 有効 な値として NULL が代入されることもあり ますし , 初期化を忘れてしまった場合には いったい何を指しているのか保証されませ ん。 なんだそれだけのこと ? などというな かれ。先にも述べたように , 安全な C て、ある ことは C 十十に要求される大事なことなのて、 す。 また , 参照て、なければならないという局 面が実は存在します。このことについては また後ほど , クラスやオペレータオーバロ ードを扱うときに述べます。 参照引数 さて , 今まて、に述べてきた参照の使い方 て、はそれほど参照のメリットが感じられな 引数にも使えるとなれば , どうて、しようか かったかもしれません。が , 参照が関数の コラム C 十十の struct, enum C 十十では , struct や enum による宣言は , そのまま新しい型を作るという行為になり ます。 C では , Fig. 4 の structA はあくまでも st 「 uct であったわけですが , C 十十では A とい う型を作ったことになるので , " st 「 uct " は不 つまり , C 十十でいう 要です。 int n, m ; typedef struct { は , C でいう int n, m , struct A { に等しいことになります。 につけ触れていきたいと思います。 体の相互参照などの細かい点は , また折り 名前空間のバッティングの間題や , 構造 参照引数を使った呼び出して、は , 引数は べもありません。 たまたま NULL て、なかった場合にはなすす も , ポインタが初期化されていないのだが , 確認しなくてはなりません。しかしこれて、 渡されたポインタが NULL て、あるかどうか すから , 汎用関数として確実を期すなら , C の場合 , input ( ) に渡すのはポインタて、 (List 5a, List (b) 。 Fig. 4 構造体の引数 struct A { int n, m , C の場合 void f00 (struct A * void bar( ) struct A a . foo(&a) : C 十十の場合 void foo(const struct A& a) / / f00 ( ) では a の内容を変更しない void bar( ) foo(a) :

2. 月刊 C MAGAZINE 1992年7月号

X 68 k 活用講座 LiSt テストプログラム 1 : #include く stream. h 〉 2 : 3 : int 4 : main(void) cout くく” X68 圓 0 は無敵だ \ n ”・ 6 : Fig. 6 コンノヾイル例 gpp test. cc ー 0 -llibg -lfloatfnc Fig. 7 BIG ENDIAN と LITTLE ENDIAN 〇 B ℃ ENDIAN マシン main( ) 発生した場合は , inline 関数として実装しなければ , クラス set GCC L 旧 S= のメンバ関数としても定義て、きます。これ て、ライプラリの拡張子が . 1 ( 工ル ) て、あること を使えばスプライトクラスも設計て、きます。 を指定してください。さらに XC Ver. 2 の 大きな拡張は上の 2 点て、す。 C マガ配布版 場合は Fig. 5 のようなメッセージて、停止しま XGCC にある拡張機能て G 十十に実装されて す。これはスタートアップランタイムが浮 いない拡張はありません。 動小数点ライプラリを呼び出しているため G 十十オリジナルとの相違点 て、 , XGCC て、も XC Ver. 2 環境て、は発生しま す。 Fig. 6 のようにコンパイルするか , めん どうて、したら floatfnc. 1 を gnulib. 1 にライプラ X68000 版 G 十十は DJGPP などの G 十十と リアンて、マージしてしまえばよろしいかと 動作が異なる部分があります。ソースの記 思います ( 注 1)0 述のやり方によってはまったく移植性がな ちゃんとコンパイルて、きたて、しようか ? くなります。 舌が前後して申し訳ありませんが , 今回付 int オプジェクト参照の処理の相違 録ディスクに収録したプログラムとライプ ラリだけて、は G 十十は動きません。 XGCC を List 3 の add char ref(char & ) 関数に 渡される char への参照の処理が G 十十オリジ 収録した際にあわせて収録した GNULIB が ナルとは異なった動作をします。関数 main 必要て、す。 ( ) て、宣言されている intx を , add char re コンパイラドライノヾに与えるオプション f ( ) に渡す場合 , オリジナルの G 十十て、は x スイッチは , DJGPP とほとんど同じて、す。 へのポインタを生成してそのまま add char 本誌 ' 92 年 1 月号に G 十十のマニュアル和訳が ref ( ) に渡します。受け取った add char r 掲載されているのて、そちらを参照してくだ ef ( ) て、は char への参照のつもりて、値を十十 さい 0Table 1 に X68000 版 G 十十が参照する します。 Fig. 7 て、示すように BIG ENDIAN 環境変数の一覧を示しておきます。 マシンて、ある 68000 と LITTLE ENDIAN マ ソースの場合にはほかの G 十十とのポータビ X68000 版 G 十十拡張仕様 シンて、ある 80386 て、は結果が異なったものに リティはありません。 なります。 in ⅱ ne 関数展開のバクフィックス XGCC 同様に X68000 版 G 十十には , 相当 List 3 の場合には char 型の匿名変数が生 成されてそれが intx て、初期化されその匿名 の拡張機能が加えてあります。ほとんどの G 十十 1.40.3 には inline 関数の展開の際 機能は XGCC と同じて、すが , 改めて列挙して 変数への参照を渡すのが正しい処理と思わ に , ある条件の下て、最適化に失敗します。 れます。これはかなり昔にネットの NIFTY おきます。なお , これらの機能はすべてキ GCC 1 . 40 て、はこのバグはフィックスされて - Surve 内「 C 言語フォーラム」て、話題になった ャンセルすることはて、きません。 いますが , G 十十て、は inline 関数を扱う inte 処理て、すが , X68000 版 G 十十て、はこのよう 1 漢字識別子が使える grate. c ( G 十十ソースファイル ) が GCC とは 漢字は識別子が現れる位置ならどこにて、 な処理がソースに発見された際には「匿名変 別個に供給されているために このノヾグカす 数を生成した」という警告を出して , 上記の も使えます。クラスの名前にも , もちろん そのまま残されています。 List 4 を参考にし 使うことがて、きます。 ように匿名変数を生成するように変更を加 てください 2 割り込み処理を行う関数を記述できる えてあります。て、すから , この警告が出る DJGPP は Ver. 1.39 ということなのて、 , →アドレスが増える方向 int X 00 00 00 05 add—char—ref に渡されるアドレス →アドレスが増える方向 00 00 00 05 add—cha 「—refC 加算される char ↑ ↑ 結果 int X →アドレスが増える方向 01 00 00 05 OLITTLE ENDIAN マシン main( ) →アドレスが増える方向 int X 一三ロ 05 00 00 00 ↑ add—char—ref に渡されるアドレス →アドレスが増える方向 05 00 00 00 add—char—ref で加算される char →アドレスが増える方向 06 00 00 00 ↑ 結果 int X X68k 活用講座 141

3. 月刊 C MAGAZINE 1992年7月号

て、お目見えしました。 C 十十の原形て、あるく C with CIasses > については , 1982 年の ACM の論文に見ることがて、きます。バイプルに よると , C with CIasses は 1980 年から AT& T 内部て、使われていたそうて、す ( ちなみに 彼が博士課程を修了したのが 1979 年て、すか ら , AT&T に入ってすぐのことて、すね ) 。ま た C 十十という名前は 1983 年に Rick Masci tti という人によってつけられ , 同年 , 初め て研究グループの外部にインストールされ たとのことて、す。 さて , 1985 年以前の C 十十 ( AT & TC 十十 1.2 ) と現在の C 十十 ()T & T C 十十 2.1 あ るいは 3.0 ) て、は基本的な部分に変更はあり ませんが , 使い勝手がよくなるよう , また コラム 新しい言語仕様の追加などて、細部がかなり 異なります。 現在 , 単に C 十十というと , AT&T C 十十 2.1 レベルのものを指すようて、す。昨年末に AT&TC 十十 3.0 が登場しましたが , パソ コンレベルて、 3.0 をベースにしたコンパイラ は , 筆者の知るかぎり BC 十十 3.0 だけのよう てす ( 本稿執筆中に , C + + 処理系となった MicrosoftC/C 十十 7.0 がリリースされたよ うて、すが , 筆者の手元にないのて、詳しい とはわかりません ) 。 1.2 から 2.0 / 2.1 のバー ジョンアップて、かなり言語仕様が変化した のに比べ , 2.1 から 3.0 のバージョンアップ はそれほど激しい変化て、はありません。 この連載て、は基本的に AT & T C 十 + 2. 1 レベルの話題を扱います。ときとして , 3. 0 の話も出てくるかもしれません。 ごくおおざっぱな C 十十の変遷を , Fig. 9 に示しておきます。 この連載て、は , Fig. 10 にあげた C 十十処 理系を対象としていくことにします。これ らは , とりあえず筆者の手元にあるものて あり , 今後の状況次第て、変わってくるかも しれません。 なるべくコンパイラ依存・機種依存は避 けたいと思っていますが , ときに易きに流 れてしまうかもしれませんい 。そのとき 載で扱う C 十十処理系 SubStory 十十 登場人物 C 子 . C ならまかしてっ プラ子 . これからはズバリ C 十十でしよう ( 死語か ? ( 笑 ) ) 等身大のぶらなりあ・・・・なんだかよくわからないぞ . ー ) C 子 : ねーねー , 知り合いのコが C 十十て、プログラム作って見せ てくれたんだけどさ , よくわかんないの。ちょっと教えて プラ子 : うん。ヘー , テキスト VRAM の内容をファイルに落と すっていうプログラムなのね ( ListA ) 。機種依存は避ける , なんて舌の根も乾かないうちから 98 依存か・・・い二ぶつぶ C 子 : え ? つ。 92 C MAGAZINE 1 2 7 C 子 . うんうん。 という型を作っているのね。 typedef BYTE TVRAM [ 25 ] [ 80 ] [ 2 ] : なってるてしよ。だから , プラ子 : ( 無視して ) 98 の VRAM って , 2 バイトて、ひとつの単位に ぶらなりあ : ぶらぶら。 C 子 : 参照は小粒てもヒ。リリと辛いってやっ ( 笑 ) ? 使い方してるじゃない プラ子 : あ , これはいわゆるひとつの参照ってやつね。しぶい れって ? C 子 : えーとね , 10 行目に TVRAM & なんてのがあるて、しよ。 プラ子 : あ , なんてもない。て , どこがよくわからないの ? プラ子 . それて、 10 行目だけど , 今まて、なら TVRAM *vram=MK FP(0xa000, の : と書くのが普通よね。 C 子 : そうね。て , ていう感じてアクセスするのよね。けど , 私時々 vram [ 3 ] [ 2 ] [ 0 ] ってやっちゃうのよ。工ラーにもならないし一一い , 困っ ちゃって。 プラ子 : そう , その間違いが起きやすいの。参照を使えば , そ のミスからは解放されるってわけね。 C 子 : て、も参照ってごちやごちゃしてるのね。 プラ子 : まあ後々の便利さのためだから , 定義のときだけは仕 方ないかも。単に * ( アスタリスク ) がひとっ余計について るだけなんだけどね。 C 子 : これて晴れて vram [ 3 ] [ 2 ] [ 0 ] としてアクセスてきるってわけね。 プラ子 : うん。それから , 参照にはもうひとっポイントがある わね。 C 子 : なに ? プラ子 : 参照は一度定義すると , 参照する実体を変えることが て、きないの。だから , まちがえて vram 十十 ; なんてやっちゃうこともなくなるわね。 C 子 : ヘー , 私おっちょこちょいだから助かる。それに参照っ て , 定義のときに必ず初期化しないといけないんてしょ ? 初期化忘れもなくなっていいわね。 プラ子 : そうね。あと , このプログラムてはインライン関数が

4. 月刊 C MAGAZINE 1992年7月号

リ The + れていた template や exception handling は , みましよう。 バイプルて、は正式に言語の一部となってい 参考文献 ます。 [ 1 ] M. A. Ellis and B. Stroustrup, TThe 次回には , クラス機構のさわりを予定し 参考文献 [ 1 ] は , ARM という名前て、知 Annotated C 十十 Reference Manual 』 , Addison-Wesley, 1989 (ARM) ています。て、は , また来月。 られている , 注釈っき C 十十リファレンスマ [ 2 ] B. Stroustrup, fThe C 十十 Program こまて、タイプして凝った肩を ニュアルて、す。 C 十十のインプリメンタや工 ート向けに書かれた本て、 , C 十十言語 ming Language Second Edition 』 , Ad キスノヾ 「すいませーん , コーヒーのおかわりおね の細部に渡って細かい考証がなされていま dison-Wesley, 1991 がいしま ~ す」 [ 3 ] B. Stroustrup, fData Abstraction in す。 ANSIC 十十標準化のべースドキュメン ふと回りを見渡すと , おかしな 3 人組が目 トにもなっています。 C, AT&T UNIX Readings and Appl に入りました。ラップトップを前に 参考文献 [ 2 ] は , C 十十のバイプルと呼 ications Volume II 』 , AT&T, 1986 やらきゃーきゃーいっていますが ( いるかそ ばれることもあり , C 十十開発者の Dr. Str んなやっ ( 笑 ) ) ・・・・・・。何をやっているのか , oustrup 自らが著わした C 十十言語について 気になる人はコラム SubStory 十十を覗いて 最新のマニュアルて、す。 ARM て、実験的とさ 使われているのね。 C 子 : inline BYTE HiByte(WORD c) { return c > > 8 : } ってやっ ? てもこれ , 私なら # define て、やっちゃうな。 プラ子 : この程度なら #define< もいいんだけどね , #define HiByte(c) ((BYTE)(((WORD) (c) > > 8 ) & 0x 幵 ) ) こんな感じて、ちょっとややこしくなっちゃうね。 C 子 : そういわれてみるとそうね。 プラ子 : マクロには型がないからキャストをきちんとしてやら ないといけないし。インライン関数なら , 関数が型を持つ から大丈夫。 C 子 : なるほどね ~ 。いいかもしんない。ても , マクロ定義だ は悪しからず・・・ 次回は 叩き , も減るんじゃないかな。効率はマクロと変わらないし。 C 子にそうね。 C 十十って意外とおもしろそうじゃない。 プラ子 : というわけて、 , 付録ディスクにはもっとしつかりした ものがついてます。 DOS/V 版もありますよ。常駐するし各 種画面モードにも対応してますから、そっちも見てくださ C 子 : 誰に向かっていってるのよ プラ子 : じゃまた来月。 ぶらなりあ : ぶらぶら。 textsave. cpp 1 : 〃一 9801 ( ノーマルモード ) 用テキスト画面のセプ 2 : れ仙 de く & t は iO 〉 3 : #include く dos 、 h> 4 : れ龜面 e く jctype. 矗〉 6 : typedef unsigned 朝 a に BYTE; 7 : typedef unsigned short WORD; 8 : 9 : typedef BYTE 卿 RA 25 ] [ 80 ] 「 2 ] ; 10 : TVRAM& 軒 a 第ネ ( TVR のー ( 0Xa000 , の : 11 : 12 : li れ 0 WORD Word(BYTE 10 : BYTE (i) ( で e い 11 ( ( 和 R の域くく 8 ) ; ) 13 : inline BYTE LoByte(WORD 0 ) ( 「 0 加新 c; ) 14 : inline BYTE HiByte(WORD c) ( return 0 》 8 : 。 ) 16 : void xtSa マ 001 阯 ) fo 「 (int y 第 0 : く 25 : y + + ) ( fo 「 (int ま 0 ; にく 80 : ) ( 20 ・ putc(vran[y] [ 灯 [ の , 朝 ) : 21 else ( 22 WORD 郎三 jistoj 用 S(W。「d(眈明[ⅵ[X]は]を”衵 [ y ] [ x ] [ の + 0 メ 2 の ) ; 23 も 0 ( HiByte ( ). fp)'v 24 putc(LOByte(ms). fp): 25 : 26 : 27 : 32 : 33 : nain(int char** argv) 34 : ( れ事 fp ま fo れ ( a 「 [ 1 懿、 t つ : 35 : TextSave(fp); 36 : fclose( (p) : 38 : 「 0 い 0 : 39 : ) List A #define HiByte(c) こんな風にしてあげれば HiByte(ch) なんて代入がてきちゃうよ。 プラ子 : 確かに , さっきのインライン関数ては無理ね。て、もま っかっせつなっさつい ( 誉 ) / 。参照をもらって参照を返せ ばいいのよ。ほら , こんな具合。 inline BYTE& HiByte(WORD& c) {return (*((BYTE*)(c) + 1)) ; } C 子 : ヘー。ヘー。おもしろいのね。 ぶらなりあ : ぶらぶら。 ( こいつはこれしか喋れないのか : ) プラ子 : ( 無視して ) もっとも , 全部が全部のマクロをインライ ン関数に置き換えることがてきるとまて、はいわないけどね。 なるべくインライン関数を使うように心掛けていればミス と C 十十入門講座 93

5. 月刊 C MAGAZINE 1992年7月号

最近では dJgpp なとにより MS - DOS マシンて も GNLJ C 十十か使える。ここては , GNIJ C 十十 付属ライプラリであるⅱ bg 十十を , そのマニュア ルてある『 LJse 「 'sGuidet0GNLJ C 十十 L ib 「 a 「 Y 』の翻訳を中心に紹介する。 GNU C 十十ライプラリマニュア丿レ 村山孝夫 GNUC 十十ライプラリ ( libg 十十 ) は , D UNIX の curses ライプラリをクラスにまと 32 , 48 ビットの精度 ) 。 めたもの。この curses ライプラリとは , 各 ougLea 氏らにより開発された GNUC 十十 Bits プログラムが煩わしい端末制御の多くを のためのクラスライプラリて、 , FSF (Free S 0 か 1 のデータを扱うために BitSet と BitS 行わなくてもよいように , 端末制御のた tring がある。 BitSet は , 0 か 1 のデータの oftware Foundation lnc. ) 社の配付する GN めの機能をライプラリにしたもの。 U C 十十に含まれている。またライプラリ 集合を扱うものて、 , BitString は , 0 か 1 の またこのほかに genclass ユーティリティを にはクラスライプラリだけて、はなく , 列を扱うもの。 使うジェネリッククラスがいくつかある。 つかユーティリテイも含まれている。 String このジェネリッククラスとしては , List, L 本特集の他章て、触れたクラスライプラリ 文字列型。 char* の代わりに fprintf, St rcmp などの引数に使える。また , 正規表 inkedList, Vector, PIex, Stack, Queu の多くは , あるひとつのクラスを根とする 階層構造を持っていた。しかし本章て、触れ 現のためのクラス Regex もある。 e, Deque, PQ, Set, Bag, Map がある。 詳しくは本誌 1992 年 5 号の「 djgcc 詳解講座」 る libg 十十は , 設計の違いから階層構造を持 Random を参照されたい これは乱数生成のために使用される。乱 っていない。つまり , libg 十十のクラスは , 数生成と乱数分散のアルゴリズムは , 用 GNUC 十十ライプラリに付属する fI_Jse それぞれ独立したクラスて、あり , libg 十十は r' s Guide 』 (Fig. 21 参照 ) の翻訳を掲載す 意されているいくつかの中から選択する それらが単に集まったものて、 , それらクラ ことが可能て、ある。 る。ただ , 誌面の関係から , 本章に掲載す スの間にとくに関係はない。 Fig. 20 におも るのは冒頭部分だけて、ある。残りは , 本誌 Data なクラスをあげる。 連載「 djgcc 詳解講座」て掲載していく予定て、 データの集まりを分析するためのクラス lnteger ある。 として SampleStatistic と SampleHistogr 整数を扱うためのデータ型。 C の int などと GNUC と GNUC 十十は Ver. 2.0 から C , am がある。 SampIeStatistic は , double 型 違って扱う数値にとくに制限はない のデータを収集し , 統計を求めることが C 十十 , ObjectiveC の三つの言語を統合し RationaI ている。ライプラリも 2.0 になった。ただ て、き , SampIeHistogram は , Histogram 有理数を扱うためのデータ型。この型は こて、は , 2.0 の GNUC 十十ライプラ を出力することがて、きる。 1 / 3 のように小数として割り切れない数値 し , リて、はなく 1.39 の解説を行った。したがっ を扱える。 C の FILE 構造体の C 十十バ て , ここて、掲載する GNU C 十十ライプラリ Complex ーション。ファ イルに対する基本操作が用意されている AT&T のクラス complex ( 複素数 ) と同等 の User' s Guide の翻訳も 1.39 て、ある。 ( 翻訳参照 ) 。 の機能を実装したもの。 本章にかぎって , GNUC 十十 Libr stream AT&T の iostream ライプラリと機能上同 ary General Public License にもとづ [ ー 1 , 1 ) の範囲の実数を扱うデータ型。 じものを実装したもの ( 翻訳参照 ) 。 いた再配布を認めます。 実際には四つのクラス Fix, Fix16, Fix CursesWindow 24 , Fix32, Fix48 がある ( それぞれ 16 , 24 , 70 C MAGAZINE 1992 7

6. 月刊 C MAGAZINE 1992年7月号

. 1 Fig . valuel ) OR (table. fieId2 : : valuel ) AND (table. fieId2 : : valuel ) AND (table. fieId2 : : vaIue2) AN D (table. fieId2 = : value2) AN D (table. fieId2 : Fig. 文を変換する例 元のかたち ((table. field 1 AND ( (table. fieId2 = 最適化後のかたち ( (table. field 1 OR ( (table. fieldl OR ( (table. field 1 OR ( (table. field 1 : valuel ) OR (table. fieldl : value2)) : vaIue2)) :valuel)) ・ value2)) : va lue 1 ) ) . vaIue2)) 2 ダイナミックな SQL 文の場合のクライアント / サーバ間の対話 1. クライアントは SQL 文をスキャンし , 参照されているデータベースのエンティティと変数を取り出 し , そして最小限のシンタクスチェックを行ないます。 SQL 文は , クライアント側で完全にはチェ ックされません。なせなら , テータベースのテープルやフィールドへの参照は , サーノヾ側にあるテ ータベースのテータ辞書に照らさないと , チェックてきないからです。 2. SQL 文は , サーバへのリクエストメッセージへとバッケージされます。そして , 参照しようとする 工ンティティと変数の名前やテータ型が , その他の入力用工ンティテイや変数とともに , そのメッ セージの中へコピーされます。 3. リクエストメッセージはテータベースサーバへ送られ , そこでアンバックされます。 4. テータベースサーバは SQL 文の語彙解析と構文解析を行ない , シンタクスとセマンティクスをチェ ックします。 5. テータベースサーバは SQL 文を最適化し , アクセスプランを決定します。 6. テータベースサーバは文を実行します。 7. 文の実行ステータスがリプライメッセージへとバッケージされ , データベースから取り出したデー タがそのメッセージの中へコピーされます。 8. リプライメッセージが , クライアントへ送られます。 9. クライアントはリプライメッセージをアンバックし , メッセージの中にある出力用工ンティテイや 変数を表しているデータをコピーします。 つう , インデクス付きデータは B ツリーにス トアされ , ツリーの葉がデータベースの個々 の行 (row) をポイントしています。 ーっの例として , それぞれ 10 万レコード の二つの表が , WHERE 節の制約に基づい て SELECT 文て、ジョインされる場合は , SELECT * FROM tablel, table2 WHERE tablel . fieldl = table2. field2 上て、 , tablel. fieldl と table2. field2 がイン デクス付きてなかったら , デカルト積 ( のよ うなしらみつぶし比較 ) を要するて、しよう。 つまり最初に , tablel を順次スキャンしてい きます。そして tablel の各行の fieldl の値 を , table2 の各行の fieldl の値と比較しま す。すなわち , このジョイン演算を完了す るために必要なデータ検索の回数は , 10 万 x 10 万 , つまり 100 億回となります。 しかし , tablel . fieldl がインデクス付きて、 あるなら , table2 は順次スキャンしますが , tablel へはインデクスによりアクセスて、きま す。そのインデクスの構造が B ツリーて、ある なら , tablel. fieldl への各アクセスに際して 要するノードの渡り歩き回数 ( 辿る中間ノー ドの数 ) は 10 のオーダーとなります。そこ て、 , データ検索の回数は 10 万 X10 , すなわ ち 100 万のオーダーへと縮減されるのて、す。 インデクスの実装方法はいろいろあります から , この数値はあくまて、も概算て、すが S QL のスタティックと ダイナミック スタティックな SQL とは , 一定の固定的 な SQL 文を使うことを指します。ある決ま った機能 , たとえば在庫管理などを実現す るアプリケーションは , そういう固定的な SQL 文を使って値の入力 , 更新 , 削除 , 検 索などを行ないます。こういう場合 , アプ リケーションの中て、 SQL 文のシンタクスは 変わりませんが , その SQL 文の中て、参照さ れる変数やカーソルは変わります。これと 逆に , ダイナミックな SQL 文は , ランタイ ムに構築されて実行されます。 たとえば , スタティックな SQL 文を使っ ている在庫管理のアプリケーションの , 管 理用の小道具として , いろいろな条件を組 み合わせてデータを検索するユーティリテ SQL のパワーを活かすために 29

7. 月刊 C MAGAZINE 1992年7月号

= = ln 種川 a ⅱな m 川計 Ma れ門 システム・ワン Power C V . 2. OJ Power Ctrace リスト操作プログラムのデバッグ リンクリストを扱う場合 が容易になります。 の効果的なテパッグ 構造体メンバの連続参照 ポインタを利用して自己参照型 構造体をリスト形式て、表現するこ とがあると思います。この場合は Fig. 1 は List 1 のプログラムをコ ポインタを使用して順序管理をし ンパイルした後 , Power Ctrace を なければなりませんのて、配列構造 起動して 49 行目の位置まて、実行し よりも扱いがめんどうになります。 たときの変数ウインドウの画面て、 リスト形式て、は追加や削除によっ す。この例て、は二重リンクの操作 て配置される位置や順序が変わっ を行っています。リンクの根て、あ てしまうために絶えず参照の関係 る base のアドレスが , を追跡していなければなりません。 0X0086 Power Ctrace て、は構造化変数 て、あり , 関数 malloc によりアロケ を展開することにより内部状態を ートされる構造体のアドレスが順 詳細に見ることがて、きます。それ 番に に加えてメンバがポインタの場合 0X832e にはそのポインタの型に合わせて 0X8338 ポインタの示す領域のデータも同 0X8342 様に表示しますのて、展開を繰り返 0X834C すことにより , 次々とリンクされ て、あるのて、 , どのようにリンクさ ているリストを参照することがて、 れたか確認て、きると思います。 きます。 展開には限界があり ( シンボルの この展開機能を使用することに 表示領域が 32 文字分しかないため よりあるリストを基点として前方 区別がっかなくなる ) リンクは前後 および後方のリストに追加や削除 各 4 段程度まて、しか参照て、きません などの処理を行う場合 , リストが が , 操作中に前後の関係がわかれ 孤立してはいないか , リストが二 ばよいのて、デバッグには支障はな 重にリンクされていないかといっ いて、しよう。 たことが容易に確認て、き , リンク リンクリストを扱う場合の例 List 1 base. next = ・ base. prev = &tzse ・ return 22 : 23 : 24 : } 25 : 26 : void insert( LIST *insptr ) 28 : LIST *tnsptr ・ 29 : 30 : 31 : 32 : 33 : 34 : 35 : 36 : 38 : 39 : 40 : 41 : 42 : } 43 : 44 : VOid 45 : { 46 : LIST 48 : 49 : 50 : 51 : 52 : 53 : 54 : } 55 : 56 : MESSAGE table[ ] { 3 , ” 3 番目に優先順位が高い。 { 1 , ” 1 番目に優先順位が高い。 58 : { 4 , ” 4 番目に優先順位が高い。 59 : ( 2 , ” 2 番目に優先順位が高い。 60 : 62 : 63 : #define LIMIT ( sizeof( table ) / sizeof( MESSAGE ) ) 64 : 65 : void main( void ) 66 : { 67 : UINT count 68 : LIST *Ptr 69 : initilize( ) 70 : for ( count ニ 0 ; count く LIMIT ; co t + + ) { ptr = ( LIST * ) 118 ( sizeof( LIST ) ) ・ 72 : if ( ptr ! = ( LIST * ) NULL ) { 73 : ptr->msg = tableC count ] 74 : insert( ptr ) 75 : 76 : / * not use base. msg * / basptr = thse. next ・ while ( basptr ! ニ &tme ) { if ( tnsptr->msg. level > insptr->msg. level ) { break ・ basptr - insptr->prev ー ; insptr->next ー thsptr bas pW >prev- >next insptr bas ptr- >prev - insptr return display( void ) *Ptr ptr = bas e. next while( ptr ! = &tnse ) { printf( "STRING = Xs*n ” ptr->msg. string ) ptr = ptr->next ・ return 1 ノーー .1 ア、、丿 display( ) ・ return List 1 1 : #include く stdiO. h> 2 : #include く m118. h > 3 : 4 : typad. ef uns igned int 5 : 6 : typedef s truct { 7 : UINT level ・ 8 : char *String 9 : } MESSAGE ・ 11 : typedef struct list 12 : struct list 13 : struct list 14 : MESSAGE msg ; 15 : ) LIST : 16 : 17 : LIST bas e 18 : initilize( VOid ) 19 : VOid Fig. 1 変数ウインドウての表示 ( 4 レベル展開時 ) 91 display LvarJ く 1 〉 extern pointer P01nter pomter polnter pointer StruCt pmnter POlnter pointer struct UINT : 0086 4 0X8338 0X834C 0X832e 0X8338 @0X8350 0X0086 0X8338 0X8342 @0X008a 2 ptr ptr—>next ptr—>next—>next ptr->next—>prev ptr->next->msg ptr—>prev ptr->prev->next ptr—>prev->prev ptr->prev—>msg ptr->msg. level ptr—〉 msg. string *pt に〉田 sg. S tr ing *. next *prev 1 for link structure * / root ” 1 番目に優先順位が高い。 響 x8 2 ' 0X8338 pointer POi nter lnformation from CompiIer Makers 163

8. 月刊 C MAGAZINE 1992年7月号

ealizi the P0tentiaI 0f SQL ィが欲しくなるかもしれません。しかし , 在庫管理のアプリケーションの中にこんな 文を実行する関数があれば , 在庫量が 100 以 下になっている品目を知ることがて、きます。 SELECT prod code, prod name FROM products, inventory WHERE products. prod code inventory. COde GROUP BY inventory. code HAVING SUM (inventory. count) く 100 しかしこれて、は , 関数が実行されるたび に条件は同じて、す。これに対し , ユーティ リテイプログラムなら , ユーザがランタイ ムに検索条件を指定することがて、きます。 そうするとユーザは , アプリケーションが 提供してくれる情報に制約されずに , 自由 にもっと複雑高度な問い合わせがて、きるよ うになります。たとえば , 高価てない品物 について , 在庫量が 100 以下のものを知りた いときは , SELECT prod code, prod name FROM products, inventory WHERE products. prod code inventory. COde AND products. price く 10.00 GROUP BY inventory. code HAVING SUM (inventory. count) く 100 ダイナミックな SQL 文は , それが実行さ れるかどうか事前には分からないのて、すか ら , 関数コールを使うのが唯一理に適って います。文は , データベースにストアして はいけません。二度と実行されないかもし れないのて、すから。 30 C MAGAZINE 1992 7 Fig. 2 に , ダイナミックな SQL 文の実行に あります。 用なのて、 , 例外処理の部分などは省略して 取り出されます。このコードは本稿の説明 ーソルがオープンされ , マッチする各行が 内部のネームテープルに入れた後 , そのカ て、す。参照される変数すべてとカーソルを List 1 は , ダイナミックな SQL のコード片 Fig. 3 プリプロセスされる SQL 文の場合のクライアント / サーバ間の対話 1. クライアントは SQL 文をスキャンし , 参照されているテータベースのエンティティと変数を取り出 し , そして最小限のシンタクスチェックを行ないます。 SQL 文は , クライアント側で完全にはチェ ックされません。なせなら , テータベースのテープルやフィールドへの参照は , サーバ側にあるテ ータベースのテータ辞書に照らさないと , チェックできないからです。 2. SQL 文は , サーバへのリクエストメッセージへとバッケージされます。そして , 参照しようとする 工ンティティと変数の名前やテータ型が , そのメッセージの中へコピーされます。文はこの時点で は実行されないので , 入力用のエンティテイや変数の値は未定義であり , メッセージの中へ含まれ ません。 3. リクエストメッセージはテータベースサーバへ送られ , そこでアンバックされます。 4. データベースサーバは SQL 文の語彙解析と構文解析を行ない , シンタクスとセマンティクスをチェ ックします。 5. テータベースサーバは SQL 文を最適化し , アクセスプランを決定します。 6. テータベースサーノヾは , 文のアクセスプランをテータベースにストアします。 7. 文のプリプロセスに伴うステータスが , リプライメッセージへとバッケージされます。出力用工ン 1 : main ( ) List 1 関数コールによるダイナミックな SQL の実行 9. クライアントは , リプライメッセージをアンバックします。 8. リプライメッセージが , クライアントへ送られます。 ティティと変数の値は未定義であり , メッセージ中に含まれません。 3 : 4 : 6 : 8 : 9 : 10 : 11 : 12 : 13 : 14 : 15 : 16 : 19 : 20 : 22 : 23 : 24 : 25 : 26 : 28 : 29 : 30 : 32 : 33 : 34 : 35 : long SQLCODE; int min_amt; char name[20] ; float price; int code; long prod_curs ; / * フ。ロク・ラム・コート・ / * ク・ローハ・ルなネームテーフ・ルにカーソルと変数を入れる . * / i f (SQL_Def ine_Cursor("prod—curs" "SELECT prod. name, prod. code, prod. price ” FROM prod, onhand ' ” WHERE prod. code ニ onhand. code AND onhand. num く :min amt ” &prod—curs, &SQLCODE) ! = の printf("Error declaring cursor. }n"); exit( の ; if (SQL_Define_Name("min-amt" SQL_INT, sizeof(min_amt), SQL_STRI NG, s izeof (name), if (SQL_Define Name("name &min-amt, &SQLCODE) name, &SQLCODE) if (SQL_Define_Name( ” code ” &code, &SQLCODE) SQL_Define Name( ” price ” &pr ice, &SQLCODE) ; if (SQLCODE ! ニの SQL_INT, sizeof(code), SQL_FLOAT, sizeof(price),

9. 月刊 C MAGAZINE 1992年7月号

Fig. 3 C の標準ライプラリ関数 sp を呼び出すプログラム [PascaI 部分ソース (SQ. PAS)] rogram sq L c sqrt} function call—sqrt(): double) : double; external ; var a: double; beg i n a ド 511 ー sqrt ( 2. の ; writeln(' sqrt(). の end. [ アセンプラ部分ソース ( C ー SQRT. ASM ) ] I DEAL MODEL TPASCAL DATASEG CODESEG EXTRN C sqrt:NEAR ; C 形式で sqrt を呼び出す 数学関数は matherr を参照している ( ここではがにもしない ) PUBLIC matherr PROC C _matherr NEAR ARG why : WORD, funcname : WORD, argl : WORD, arg2 : WORD, retva 1 : QWORD ・ nothing fldz , return 0.0 ret Fig. 1 PXENGINE. PAS の追加テータ (837 行目 :implementation の直前 ) { あいまい検索 } function PXSetSrchAimai( Aimai : lnteger) : lnteger; functi on PXA ima i Srched ( var IsAimai : lnteger) : lnteger; ( 916 行目 : end. の直前 ) function PXSetSrchAimai ; external ' PXENGWIN' index 104 ; function PXAimaiSrched; external ' PXENGWIN' index 105 ; Fig. 2 間接的に C の標準ライプラリ関数を呼び出すプログラム CPascal 部分ソース (EQUIP. PAS)]] program equ 1 L c—pc98eq L pc98eqip function call—pc98equip: WORD; external ; var : WORD; begin eq : ニ call—pc98equip; write(' system clock: ' ) ; if ()q and $ 08 ) く > 0 then writeln('8MHz' ) else writeln(' 5MHz' ) ・ write(' resolution: if ( and $ 800 の◇ 6 then writeln(' high' ) else writeln('normal' ) ; end. ENDP PUBLIC PROC cal l_sqrt call—sqrt NEAR ; QWORD(double) 型の引数をとる val :QWORD Cval] ; 引数をコプロセッサのスタックに取得 CQIORD vrR bp-8] , ・引数をそのままスタックに転送する ; s rt の呼び出し sqrt り値はコプロセッサのスタックに sp, 8 ; 返されるので、そのまま戻る ; C で浮動小数演算を使うプログラムから ; 必ず参照されるシンボル名 ARG fld sub fstp fwait call add ret [ アセンプラ部分ソース ( C ー PC98EQ. ASM ) ] I DEAL MODEL TPASCAL CODESEG EXTRN C pc98equip:NEAR ; C 形式で pc98equip を呼び出す ; PASCAL 形式の関数定義 PUBLIC call_pc98equip PROC call_pc98equip NEAR call pc98equip ret ENDP PUBLI C TURBOFLOAT PROC TURBOFLOAT ENDP END [ SQRT. OBJ の作成手順 ] TLIB MATHS *SQRT るプログラムは , そのヘルバルー クすることはて、きません。 チンカ℃のライプラリ関数にしかな ※プログラミングに関する一般的 いため , Turbo Pascal て、はリンク なご質問は , マスタディスク中の がて、きます。 sqrt を呼び出すプログラムを Fig. 3 て、きなくなります。結果的には , HELPME ! . DOC にも記載されて 浮動小数演算を使っているモジ に示します。 Turbo Pascal のためのモジュール おります。テクニカルサポートセ 実際には , Turbo Pascal と Tur ュールについては , 数学関数を使 は最初から Turbo Pascal 用に書き ンターて、は個々のプログラムに関 boC 十十 / BorlandC 十十のやりと 直してしまうのが効率よく安全な わない簡単なものて、あれば可能な するアドバイスやデバッグについ りにはアセンプラに関するかなり 手段だといえます。 こともありますが , 数学関数を使 ては承っておりませんのて、 , 個々 詳しい知識が必要となります。ま っている場合は , 8087 や turboF なお , Turbo Pascal には . OBJ の問題についてはマニュアル , RE た , そうした点について注意して loat などのグローバル変数が使われ 形式のファイルを作成する機能が ADME, HELPME ! . DOC などを もなお数々の制約が残ります。例 るため非常に難しくなります。上 ないため C / C 十十のプログラムから 参考にしてください 己の方法て、 C の標準ライプラリ関数 えば , C て、 ng 型の乗算を行ってい Turbo Pascal のモジュールをリン ENDP EN D [ PC98EQ 旧 . OBJ の作成手順 ] TLIB CS *PC98EQIP 三一口 lnformation from Compiler Makers 167

10. 月刊 C MAGAZINE 1992年7月号

リ The + クを扱う関数て、 , 自明の引数は BASIC のよ C 十十はまたひとっ , プログラマの肩の荷 うに省略て、きればなあと思うことがありま を降ろしてくれたといえます。 す。 BASIC とまったく同じというわけには テフォルト引数 いきませんが , C + 十て、はある程度この要望 がかなえられています。それが , デフォル C 十十が私たちにもたらしてくれる恩恵は ト引数の機構て、す。 まだまだあります。たとえば , グラフィッ 参照引数 ( C の場合 ) 必ず実体を指しているわけて、すから , この ような冗長なチェックは必要ありません。 そのほかにも , 本来ならば値渡しにする ところを , 言語仕様の制約や効率の面から ポインタ渡しにせざるを得なかった場合が あります 0Fig. 4 のように構造体を引数にと るような関数がそれに該当します。 C 十十て、 あれば参照渡しを使うことにより , 呼び出 し側はポインタ渡して、あるかどうか気にせ ずに済むようになります。不用意な変更が 行われるのが嫌て、あれば , const をつけてお けば大丈夫て、す。 インライン関数 インライン関数は , 一言て、いうと C て、の # define プリプロセッサ命令によるマクロに当 たります (List 6 ) 。関数呼び出しによるオー バヘッドを避けるのが , その一義の目的て、 す。 しかし , いみじくも「関数」と名づけられ ているとおり , プリプロセッサによる単純 な置換とインライン関数には , 100 万倍くら いの違いがあるのて、す。 マクロを使った場合には , どうしても避 けられなかった危険が存在しました。 Fig. 5 を見てください。このマクロ定義 は , 2 年前ほどに作ったある C プログラムか ら取ったものて、すが , なんだかカッコが多 くてとても見やすいとはいえません。しか し , マクロ定義において安全を期すために はこれらのカッコは必要て、した。 ところがこれだけの配慮を払っても , 危 険性を皆無にすることはてきなかったのて、 す。たとえば , Fig. 5 (b) のような呼び出し が行われたら , もうアウトて、す。ポインタ p のインクリメントは一度しか行われない とを期待していますが , 場合によっては二 度行われてしまいます。 インライン関数の機構は , このような危 険性から我々を開放してくれます (List 7 ) 。 インライン関数はれつきとした関数てすか ら , Fig. 5 (b) のような呼び出しをしても , ポインタが何度インクリメントされるかと 悩む必要はさらさらありません。 LiSt 1 : #include く stdio. h> 3 : void input(int *ip, double* dp) char buf[BUFSIZ] : 5 : 6 : puts ( ” lnput int ” ) ; gets(buf) ; 8 : if (ip = NULL) ( 9 : 10 : fprintf(stderr, exit(l); 11 : 12 : *ip ニ atoi(buf); 13 : puts( ” lnput double ” ) ; 14 : gets(buf) : 15 : if (dp ニ NULL) { 16 : fprintf(stderr, ” dp is NULL#n ” ) ; 17 : exit(l); 19 : *dp ニ atof(buf) ; 20 : 22 : 23 : void main() 24 : ( 25 : int n; 26 : int *np = &n; double a; 28 : double *ap = &a; 29 : input(np, (p) ; 30 : printf("n=%d, a=Xlf}n", n, a) ; 31 : 32 : } ip is NULL}n ” ) ; 参照引数 ( C 十十の場合 ) List 1 : #include く stdio. h 〉 3 : void input(int& iref, double& dref) char bufCBUFSIZ] ; 5 : 6 : puts("lnput int") : 7 : gets(buf) ; 8 : iref ニ atoi (buf) ; 9 : puts ("lnput double") ; 10 : gets (buf) ; 11 : dref = atof(buf) ; 12 : 13 : } 14 : 15 : void main() 16 : { 18 : 19 : 20 : 21 : int n; double a; input(), a) ; printf("n=Xd, a=Xlf*n", n, a) : C 十 + 入門講座 89