特集 最新 C ・ C 十十コンバイラオーバビュー ョンなどの情報の保存がて、き , プロジェク インラインアセンプリ機能 ト管理は非常に楽になる。その結果プログ MS-C Ver. 6.0 の目玉は何といっても P WB て、ある。 PWB とは , プログラマーズエ ラマは安心してプログラミングに力を注ぐ ことがて、きるようになるだろう。 デイタ , コンパイラ , リンカ , CodeView, また , プログラムの構造を解析して関数・ NMAKE, SourceBrouser, Microsoft Ad 変数などの定義部分 / 参照部分へ素速く移動 ⅵ sor を統合するものて、 , これらを基盤にプ したり (Source Brouser) , いって、もどこか ロジェクト管理機構を実現している。 らて、も簡単に MS ー C 全体のヘルプを参照する PWB 上て、は , MakefiIe の自動生成や , タ (Microsoft Advisor) といったことが可能な ーゲット / ファイルごとのコンパイルオプシ のて、 , ソフトウェアの開発効率は格段にア ップする。 最適化については , グローバルな最適化 が実現された。すなわち , 重複する部分式 をひとつにまとめるという作業の対象を , ループから関数全体に拡大している。ほか には , 変数を自動的にレジスタ変数に割り 当てるようにしたり , ローカルコードの最 適化 , プラグマによる最適化レベルのきめ 細かな管理などがて、きるようになった。 新しい言語仕様についても触れてみよう。 引数のレジスタ渡しは , LSIC ー 86 て、はデ フォルトて、備わっている機能て、あるが , 関 数への引数をスタックを介さずレジスタを 使って行うというものて、ある。 List 9 のプロ グラムは , レジスタ渡しを使ったときのほ うが , そうて、ないときより 3 割ほど高速にな ただ , 少々最適化が甘く , List 9 の関数 a dd ( ) は , MS-C Ver. 6.0 だと , ; AX = = a, DX = mov CX, ax mov ax, dX add ax, cx ret とコンバートされてしまうのが残念て、ある。 ちなみに , LSI C ー 86 て、は , Microsoft Advisor ( オンラインヘルプ ) 上記を統合する Programmer' s Work -Bench (PWB) 環境 OS / 2 プログラミングのサポート 高速化 より洗練された最適化機能 引数のレジスタ渡し based 型変数 List 引数のレジスタ渡し 十 0 0 : 0 0 、 1 0 00 4 ′ 0 6 ? ー 8 9 0 1 ・ 0 々 1 ム 1 ・、よ far ポインタを使った例 1 : main() int far * vram; 3 : int i, j; 4 : for(j 0 ; j く 256 ; j + + ) { 5 : / * テキストセグメントを指す * / 6 : vram = (int far * ) 0Xa0000000 ; for(i 0 : i く 80 * 25 ; i + + ) 8 : / * ここでいじる * / 9 : *vram 十十一 = j; 10 : 11 : lSt based ポインタを使うように書き換えた List 10 1 1 : main() 3 : キストセグメントを指す * / —segment tvseg = 0Xa000 : 4 : int register based(tvseg) *tvram; 5 : 6 : int i,j; for(j = 0 : j く 256 : j + + ) ( 8 : tvram = 0 : for(i ー 0 ; i く 80 * 25 ; i + + , tvram + + ) 9 : / * ここでいじる * / 10 : *tvram ト j; 12 : ; AX = = a, BX = add ax, bx ret となるのだが・・・ based ポインタを使った例をあげてみよ う。以前はテキスト VRAM などのような特 定のセグメントを直接操作するには far ポイ ンタを使うしかなかった (List 10 ) 。これを 特集最新 C ・ C 十十コンパイラオーバビュー 49
工ル・エス・アイジャパン lnformation from C0mpiler Makers LSI C -86 Ver. 3.3 今回は 7 月にバージョンアップさ れた LSI C ー 86 Ver. 3.3 の Q&A と バグ情報を集めました。 cf error (devectorize : ary) のエラーになる。 ・ List 2 のように immediate を far pointer にしてリダイレクトする ソースをコンパイルするとキャ ストが正しくされず正しくない Q Fig. 1 のようにコンバイルしプ コードを生成する。 ロファイラを実行しましたが , Fig. ・ List 3 のように関数内て、 far デー 2 のようなメッセージが出力されて タの配列を extern 宣言すると Fi プロファイラが動きません。なぜ g. 3 のような Warning が発生す でしようか ? ・ cg86 のバグ A 次のように拡張子 . c をつけて ・ List 4 をコンパイルすると正しく 厄 c でコンバイルしてプロファイラ ないコードを生成する。 ・ライプラリのバグ を実行すると正常に動作します。 ・ getcwd ( ) がエラーの場合に 0 を > lcc -p test. c 返さず正常に終了する。これは , > test getcwd ( ) に誤りがあるため > prof これば , test. exe を実行したとき て, 修正は List 5 のようにライプ に作成される prof. out にソースファ ラリソースファイル dos. 1 の ge イル名として test. c て、なく test とい tcwd ( ) に①の行を挿入する。 う名前が出力されるため , prof を実 ・ scanf ( ) て、フォーマット文字列 行したときにエラーとなっている 中の空白に対応する入力の空白 のてす。 がスキップされない。 fmtio. 1 の scn ( ) に誤りがあったためて、 , 修正は List 6 のように fmtio. 1 の scn ( ) を変更する。 List 6 の中の < ! > マークをし てあるところが修正箇所て、す。 List 2 List 1 3 : 1 : #include く stdiO. h> 2 : int nin(void) char b [ 8 の 4 : 5 : puts ( (gets (b) , b) ) : 6 : 6 行目でエラーになるり 7 : 8 : return 0 : * (char far の 0X12345678 12 : Q&A List 3 1 : main() extern char far data [ 10 ] : 3 : 4 : dataC0] 5 : List 4 int b, int c, int d, int e) 1 : long ca12(int a, return ( ( 10 ) ( ( a ー c) 十 (b - d) * (e ー c + 1 ) ) ) : 3 : List 5 dos. 5 の修正 1708 : jnb ー 1 1709 : 1710 : 1711 : 1712 : ー 1 : 1713 : 1714 : 2 : CALLX —seterrno—## mv ax, ー 1 / 事①り jnp ー 2 xor ax fmtio. 1 の修正 List 6 バグ情報 ・ cf のバグ ・ typedef void v ; がコンノヾイル て、きない 0 ・ List 1 をコンパイルすると puts ( ) を呼び出しているところて , >lcc -p test > test > p 「 Of Fig. 2 NO such file or directory ” "prof : test . Fig. 3 wa 「 ning ・ type modifie 「 on 'data' ignored" 0 O ・ん ーー 0 0 前 修 / * skip space り ↓ 〈修正後》 1029 : 1030 : _scnCount = ー 1 : 1031 : nassign = nconv = 0 : 1032 : for (;;) ( ー 1033 : 0 = for 国十十 : if (isspace(c)) ( ー 1034 : do ( ー 1035 : c = 事 for 第 + 十 : / * sk i p / ー 1036 : } while (isspace(c)); ー 1037 : ugetfun(—scnSkipsp()); / * 03- Sep ー 1991 by pnori ー 1038 : ー 1039 : if ( 0 = 1040 : goto —end; 1041 : 1042 : 1043 : 158 C M AGAZIN E 1 1 12
ング添削 プログラ 敗したときに , 無理矢理書き込みなどの操 =p [ 9 ] * ( p 十 9 ) 作を行うと , 予想もしない領域を破壊して しまうことになります。 List 6 のように記述 の図式が成り立ちます。このように , 動的 すべきて、しよう。 に確保した領域を配列のように使えるよう になります。 List 2 のプログラムは , List 5 のようにし 領域の確保に成功したかどうかを必ず なければなりません。しかし , この関数を 判断し , 失敗した場合はそれなりの対 何度も呼び出すと , 実行時工ラーとなるて、 処をせよ しよう。なぜならば確保した領域をまった く解放していないからて、す。 Fig. 2 配列の確保 p [ 0 」 p[1J p[2J pC3] pC4] pC5] pC6] p[7] pC8] pC9] ・まとめ 自分で動的に確保した領域は , 責任を 今回は , 一般的な C の話をしました。次回 持って解放せよ は , 具体的に QuickC と QuickBASIC とのリ ンクのメカニズムなどについて考えること また確保に失敗したときの対策がほどこ されていないのも問題て、す。領域確保に失 にします。 List 2 に手を加えたプログラム TabIe 1 メモリの動的確保・解放を行う関数の概路 calloc List 1 : #include く stdlib. h 〉 2 : 3 : void rank(int *a, int *r, int int m) int i; 5 : 6 : int *COunt; 7 : count = cal 10C ( m + 2 , sizeof(int)) ; 8 : for (i ニ 0 : i ← m; i + + ) count[i] 9 : for (i = 0 ; i く n; i + + ) count[aCi]J + + ; 10 : countCm + 1] 11 : for (i = m; i 〉 0 ; i--) count[i] + = countCi + 1 ] ; 12 : = countCa[i] + 1 ] ; for (i = 0 ; i く n; i + + ) rCi] 14 : } VOid * callOC (size t n, size t size) ・ 大きさが size バイトである n 個のオプジェクトの領域を確保す 解説 る。確保が成功した場合は , 領域のすべてのビットを 0 で初期 化し , その領域の先頭へのホインタを返す。失敗した場合は , NULL を返す malloc 解説 void * malloc (size t size) ・ 大きさが size バイトであるオプジェクトの領域を確保する。確 保が成功した場合は , その領域の先頭へのポインタを返す。 失敗した場合は , NULL を返す List 5 に手を加えたプログラム List Ø * ・ 1 1 人 0 っ 0 4 ′ 0 6 ロー 8 9 0 1 り介 0 4- 0 ^ 0 ー 8 1 よ 1 よ 1 よ、よ , よ、ー 4 , 1 1 ム・ー亠 free 形式 void free (void * p) 解説 f 「 ee は p が指す領域を解放する。ただし p が N ULL のときは何も しない。 p は calloc, malloc, 「 e 訓 oc によって確保された領域 へのポインタでなければならない int i; int *count; count = calloc ( m + 2 , sizeof(int)); = NULL) if (count return( の ; i + + ) count[i] for (i = 0 ; i く = m; i + + ) countCaCi]] + + ; for (i = 0 ; i く n; countCm + 1] ー ) countCi] + = count[i + 1 ] ; for (i ニ m; i > 0 : 1 ー i + + ) rCi] ニ countCaCi] + 1 ] ; for (i ニ 0 ; i く n; free(count) ; return(l) ; 136 C MAGAZINE 1991 12
き渡し方法て、コンパイルする。 旧 M VS FORTRAN とコン / ヾチプルのモード を追加 スイッチ / 4 { Y ー N} V を指定すると IBM VSFORTRAN とコンパチプルのモード ソースプラウザデータベース て、コンパイルされる。 のオプションスイッチの要約が表示され /help て、 QuickHelp が起動され , / ? て下 ig. 2 FL コマンドのオンラインヘルプ 作成するスイッチ / FR が追加された。 成するスイッチ / Fr と拡張データベースを ソースプラウザの標準データベースを作 るが , 各次元の大きさと範囲は実行時に 配列の次元数はコンパイル時に決定され 配列の動的割り当て った。 いたが , near ヒープから獲得されなくな ると near ヒープからもヒープを穫得して ようになった。従来は far ヒープがなくな far ヒープの管理が MS - C Ver. 6.0 と同じ ヒープ管理の変更 も付属している。 様の API を持っグラフィックスライプラリ されている。また , MS-C Ver. 6.0 と同 TabIe 1 に示す関数 / サプルーチンが追加 新しい関数 / サプルーチンの追加 追加 INTEGER* 1 と等価の BYTE データタイプの c が追加された。 ンの大文字小文字を無視するスイッチ / Z PASCAL キーワードて修飾されたルーチ の無視 PASCAL キーワードルーチンの大文字小文字 ッチ / n010g0 が追加された。 FL コマンド起動時のロゴを省略するスイ コンパイラロゴの未表示 (ACCESS='APPEND' ) が追加され , ファイルのオープンに APPEND モード APPEND モードの追加 決定て、きる。 フ Fig. 2 コンバイルドライノヾ FL のオプションスイッチ /link く linker options and libraries> /Lr link compatibility mode executable /F く hex—number> stack size (hex. bytes) ・ LINKING / ? display this information /Wx make a11 warnings fatal /V く string 〉 set version string /NT く name> set text segment' s name / N くれ a > set text segment' s name /MW support Windows /MD DLL /help display online help /D く name>[=text] define macro /Aw Windows DLL ・酊 SCELLANEOUS /FPi87 inline with 8087 /FPc87 calls with 8087 library /FPa calls with altmath ・ FLOATING POINT /Zp [n] pack s truct on n-byte boundary /Zi symbolic debugging information /ZC ignore case 0f PASCAL rout i nes ・ LANGUAGE /PR add expanded Source Browser info /FO く object file> /FI[ く object listing file>] /Fc[<mixed object/source listing fi le>] /Fe く executable file> /Fa[ く assembly listing file>] ・ OUTPUT FI LES /Gt[ く number>] data size threshold /Gi incremental linking /Gb backward compatibility /GO 8086 instructions ・ CODE GENERATION /Ox x. optimization ( / 01t /Gs) /OS optimize for space / 01 enable 100P 叩 timizations / 0 enable optimization (same as /Ot) ・ OPTIMIZATION /AH huge mode 1 / med ium mode 1 ・ MEMORY MODEL /Sp く number> 1 isting page size /SI く number> listing page width ・ SOURCE LI ST INGS /4{YlN}v conform to VAX extensions /4{YlN)s strict syntax / 4 { 幻 N }f free-form format /4{YIN}b debug / 4 { ⅵ n } 6 FORTRAN 66 /4cc く string> conditional compilation ・ METACOMMAND 式の中て、配列をオペランドとすることが 配列の演算 ァイルの終端に自動的に移動する。 /Ss く sub-title> Listing sub-title /St く title> listing title /4{ylN)V enable IBM VS compatibility /4(Y (N)t truncate variable names /4{YlN)i conform to IBM extensions /4{YlN)d declare /4{Y (N)a make variables AUTOMATIC / 41 { 幻 4 ) default integer size optimize for speed enable precision optimizations disable optimizatlons /AL large mode 1 /Gw Windows calls /Gs disable stack checking /Ge enabl e stack check i ng 286 instructions /0t /0p /0d /G2 /X ignore ” include file ” paths /W く number> warning level /Tf く file 〉 compile file without . fo 「 / n010g0 suppress 10g0 display /ND く name> set data segment' s name /MT support multi-threads /I く name> add ” include file ” path /H く number> external name length /c compile only, no link /Lp 1 ink protect mode executab 1 e /Lc link compatibility 田 e executable /FPi inline with emulator /FPC calls with enulator /Zs syn tax check on 1 y /ZI remove default library inf0 /Zd line number information /Fs[ く source listing file>] /Fr add basic Source Browser infO / F 田 [ く皿 p file>] /FbC く加聞d executable fi le 〉 ] て、きるようになった。 DO ループを使わな くても同じ大きさのふたつの配列を直接 加算て、きる。同様に配列の各要素から定 数を引いたり , LOGICAL 変数のふたつの 配列を論理比較することも可能。また , 配列を組み込み関数または外部関数に引 き渡すことがて、きる。行列演算などて、配 列を扱うことの多い FORTRAN て、は便利 な機能てあろう。 AUTOMAT ℃変数 AUTOMATIC 文を使ってローカル変数を スタックに割り当てることがて、きる。 条件つきコンパイル $DEFINE, $UNDEFINE, $IF, $ELSE, $ELSEIF および $ENDIF のメタコマンド が追加され , 条件っきて、コンパイルする DO WHILE 文が追加された。論理条件が DO WHILE 文 ことがて、きる。 28 C MAGAZINE 1991 12
" ( ダブルクオーテーション ) を ' ( シング 行の終わりのコメント ルクオーテーション ) と同じように文字定 行の途中から ! 記号て、コメントを開始す 数のデリミタとして使用て、きる。 ることがて、きる。文字定数やホレリス定 SELECT CASE 文 数て、ない ! 記号から行末まて、をコメント C の switch 文と同じ機能の SELECT CAS とみなす。 排他的論理和 . XOR. E 文が追加された。条件式は INTEGER, L 排他的論理和 . NEQV. 演算子と同じ機 OGICAL, CHARACTER * 1 て、ある。 CA 能の . XOR. が追加された。 SE 並びの値は 1 個の値 , 範囲またはその組 み合わせて、指定て、きる。 CASE DEFAU IMPLICIT NONE 文 LT 文て、デフォルトの処理を指定て、きる。 IMPLICIT NONE 文は暗黙のデータ型宣 構造体 言を禁止する。明示的に型宣言されてい ない変数はコンパイル時に警告がて、る。 ューザ定義の構造体と呼ばれるデータ型 を定義て、きる。 RECORD 文て、特定の構造 INCLUDE 文 体に対する変数を定義する。 指定されたファイルをその場所に展開し , シンポルテープルの拡張 コンノヾイルする。 ループの最適化 シンボ、ルテープルの配置を near メモリか ら far メモリに変えたため , より多くのシ $LOOPOPT, $NOLOOPOPT メタコマン ドて、ループの最適化の有無を制御て、きる。 ンボルを扱えるようになった。 NAMELIST 文 $TRUNCATE 6 文字より長い変数名て、 , 6 文字より後の NAMELIST 文は変数グループを定義し , グループ単位て、書式っきファイルの読み 部分が必要ないときは $TRUNCATE メタ コマンドて、指定する必要がある。 書きをひとつの入出力文て、行う。 論理演算での数値引数 論理演算子 . AND. ,. OR. ,. XOR. ,. EQV. , . NEQV. および . NOT. は INTEGER 引数も 処理し , 結果は論理値て、はなく , 整数値 MS-C Ver. 6.0 と同様に Programmer's によるオペランドの比較て、得られた値と WorkBench ( 以下 PWB と略す ) の統合環 なる。 境が用意されています ( Fig. 3 ) 。 ' ( ダブルクオーテーション ) 工デイタ機能には , ・レコードマクロ機能 ・マルチウインドウ , マルチファイル ( 8 個 まて、 ) ・複数レベルのアンドゥ , リドウ ( 255 レベ ルまて、 ) ・マウスのサポート ・カスタマイズ機能 など , おなじみの機能が用意されています。 もちろん , ソースプラウザデータベース , M AKE, オンラインリファレンス (Fig. 4 ) など の機能も備えています。 統合環境は慣れれば非常に便利なのて、す が , 筆者の場合 , 手に馴染んだ工デイタと Table 1 追加された関数 / サプルーチン 関数 / サプルーチン 説明 DOS システムコールの実行 爪 TDOSQQ DOS システムコールの実行 ( セグメ INTDOSXQQ ントレジスタ使用 ) 演算ライプラリのエラー処理 MATHERRQQ シグナルの送信 RAISEQQ 割り込みシグナルの処理 SIGNALQQ 1 より大きい最小の値を返す EPSILON n 番目のコマンドライン引数を返す GETARG HUGE 正の最大値を返す 文字列の長さを返す LENTRIM テータ型についての正の最大値を MAXEXPONENT 返す テータ型についての負の最小値を MINEXPONENT 返す コマンドライン引数の数を返す NARGS 与えられた値にもっとも近い値を NEAREST 返す 文字列内の文字セットの検索 SCAN 正の最小値を返す TIN Y 文字列内の文字セットにない文字 VE 印 FY の検索 TRUE の間ループを実行する。 CYCLE 文 C 言語の continue 文と同じ機能の CYCLE 文が追加された。 DO 文や DO WHILE 文 の最初に制御を戻す。 E 刈 T 文 C 言語の break 文と同じ機能の EXIT 文が 追加された。 DO 文や DO WHILE 文のル ープの直後に制御を移す。 END DO 文 DO 文や DOWHILE 文のループを終了さ せる ENDDO 文が追加された。 Fig. 3 PWB の画面 ( コンバイル ) File Edit View Search Make Run 0pt i ons Browse 20 ー 2 ) 50 , 50 , 40 30 40 50 60 70 80 100 統合環境 HeIp ↑ GOTO 60 TO 100 ー 1 ) 70 , 80 , 80 END ループ 6 ー整数演算と配ダのアドレッシングです . 整数 J, k, 1 の値はルーを繰リ返しても変化しません . + + + PWB [E:YUSR) Compile S 柵 . FOR fl /c /0t / FoS . obj SWHET. FOR Microsoft (R) FO N 0ptimizing CompiIer Version 5.10.0000 lfortran く FI ニ Help 〉く Alt=Menu> く F6=WINDOW> ↓ 00148.001 29 速報日本語 MS-FORTRAN Ver. 5 コ
lnformation from Compiler Makers BorlandC 十十のランタイムラ イプラリソースコードを申し込み たいのですが , どうすればよいの でしよう。 リを増やすようにしてください 72 : ) 88 : ( 99 : ( farString far& c : *(new farString); 29 : ) 40 : } 42 : } ; 48 : } 54 : } 66 : } 151 : ctrl-R : MacPageUp; 158 : ctrl-Z : MacScrollUp; 160 : / 事 162 : bksp 169 : end A プログラマーズガイドの末尾 にあるランタイムライプラリソー スコードの申込書にて弊社に直接 0 ご注文ください List 1 fa 「クラスを使ったプログラム例 69 : 70 : 73 : 75 : 76 : 77 : 78 : 79 : 80 : 82 : 84 : 86 : 89 : 91 : 92 : 93 : 94 : 95 : 97 : 100 : 101 : 102 : 103 : 104 : 105 : 106 : 107 : 108 List 1 87 : farstr ing operator + (const farString far& const farStfing far& b) printf("X. *Fs*n ” , len, str); 83 : void farString: :disp(void) { return *thi S : fmemmove(str, s. str, len); str = (char far *)farmalloc(len); len = s. len; if (str) farfræ(str); i f (&s this) return *this; 74 : farString far& farString: farstring far& s) ( len = 0 ; str : NULL; farfræ(str); 68 : farString: :¯farString() ( 4 : 6 : 7 : 9 : 10 : 11 : 12 : 13 : 14 : 15 : 17 : 18 : 19 : 21 : 25 : 26 : 28 : 30 : 32 : 33 : 34 : 35 : 36 : 38 : 39 : 41 : 44 : 49 : 51 : 52 : 53 : 55 : 58 : 59 : 63 : 65 : 1 : #include く stdiO. h> 2 : #include く string. h> 3 : #include く a118. h > 5 : class far farString ( char far* str; size_t len; 8 : public: farString() : 〃 far オブジェクトを生成できるクラスの宣言 farString tmp : tmp. str ニ (char far *)farmalloc(a. len + b. len); tmp. len : a. len + b. len; i f (). str) ー f 田 e 田 mo 肥 (tmp. str, a. str. a. len) : i f (). str) —fmemmove (tmp. str + a. len, b. str. b. len) : return tmp; farstr ing(cons t char far* P) ; farString(const char far* p, size—t num); farString(const farString far& s); ¯farString(); farString far& operator=(const farString far& s); / / 動作を確認するための表示関数 void disp(void); fr iend farstr i operator+ (const farstring far& const farString far& b) : / / 動的なオブジェクトは far ヒープ領域上に生成する void far * 0 「 ator new(size—t nun) ( return farmalloc(num); ) 98 : void main() void 0 ratO 「 de 1 ete (void far (P) { farfree(p) 22 : #if く 0X297 23 : extern ” C ” ( 24 : / / Tu& C + + のための far ポインタを扱う文字列関数 size_t far -fstrlen(const char far (P) { fO 「 (size_t num = 0 : *p; num + + ) return num; 31 : void far * far —fmemmove(void far *dest' char far *dp : (char far *)dest ; char far *SP : (char far *)src; while (num) ( far *src, size—t nun) ( num— return dest : farstr ing far& a = * (new farString( ” ABCDEF ” ) ) : farString far& b = *(new farString("12345 ” )): c. disp(); C = a 十 b; b. disp(); a. disp(); 2 DEFAULTS. TEM const VOid size_t num) List 43 : #endif 45 : farString: :farString() ( str = NULL; len = 0 ; 50 : farString: :farString(const char far *P) fstrlen(p); len - str = (char far *)farmalloc(len) ; fmemmove (str, P, len) : 56 : farString: :farString(const char far 夘 , len ニ nun; str = (char ね「 *)farzlloc(len); fnenmove(str, 店 len); 62 : farString: :farString(const farstring far& s) ( len = s. len; str = (char far *)farmalloc(len); fmemmove(str, s. str. len); Ctr 1 tab rgar 170 : dnar ・ lns - ファンクションキーおよび特殊キー ctrI-Y : MacDeleteLine; 156 : ctrl-x : begin CursorDown; PaintScreen; end; 155 : ctrI-W ・ MacScrollDown; ctr I-V : Togglelnsert : ctr I-T : De IeteWord : 152 : ctrI-S : CursorSwitchaiLeft; -P : LiteralChar• 174 : 172 : 168 : 167 : 165 : 163 : 161 : 159 : 157 : 154 : 153 : 150 : 175 : ctrl-rgar : WordRight; ctrl-lfar : WordLeft; 173 : del : : Togglelnsert; 171 : pgdn ・ MacPageDown ・ Cu 「 SO 「硎 : PaintScreen; end; Right0fLine; CursorSw i : I far : CursorSwi tchedLeft : 166 : %up . MacPageUp; CursorUp : 164 : hone ・ Left0fLine; SmartTab; BackspaceDe lete : ←書き換える ←書き換える lnformation from Compiler Makers 157
関数を呼び出すようにしている ( なお , Bor 構を使いやすくし , 効率のよいプログラム landC 十十の C モードて、は , 生成コードに変 を作成て、きるような機能も考えられてきた。 化はなかった ) 。 Turbo C て、の es* インタや MS-C Ver. 6. これまて、も Turbo C の huge;tk インタは , 0 の based7* インタがそれて、ある。 オフセット値を 0 ~ 0xF に正規化すること これらは , far, huge ポインタの 32 ビット て、 , ポインタから正の方向に対して余裕が ポインタを用いることなく , IM バイトのメ て、き , 構造体のアクセスによってセグメン モリ空間をアクセスて、きる。 near ポインタ トをまたぐ危険性は少なかったのだが , C 十十 同様 , もつばらオフセット値を操作するの て、は継承によってクラスが巨大になった場 だが , そのときのセグメントの値を自由に 合や , 配列上にクラスが配置されクラスへ 変更て、きるようにしたものて、ある。 のポインタがセグメント境界に近くなった MS-C の based'* インタを例にしてみよ 合に比べ , 1 . 5 ~ 2 倍程度の高速化を実現す 場合に対処してか , よりいっそう安全な方 フ。 法が取られるようになったようて、ある (Fig. Turbo C て、も , int es * off ; と , es* segment seg int based(seg) *off ; インタを用いれば , 同様の高速化が可能て、 LatticeC て、は , セグメントをまたがない と記述する。 seg という変数がセグメント値 あるが , off のアクセスの直前に , いちいち ように構造体にパディングを当てる機能が を保持し , off という変数がそのセグメント ES レジスタを設定しなければならない点が ある。 に対するオフセットを表す。ポインタ off を 煩わしい。 Turbo C 十十から設けられた s 通常のポインタのように使えば , 自動的に eg ポインタは , 前記 segment 変数と似てい セグメント seg が仮定され , seg : off のアド るが , 32 ビットのアドレスを得るためには レスをアクセスて、きる。 seg, off とも 16 ビッ 適当な near,'tk インタと陽に足し合わせる必 このように高度な処理を行う huge ポイン ト幅て、あり , とくに off をレジスタに割り付 要がある。 タをサポートする一方て、 , セグメントの機 けることて、 , far や huge;* インタを用いる場 char seg * seg char near *Off Fig. 2 Borland C 十十 Ver. 2.0 によるコンノヾイル結果 huge ポインタのテストプログラム List 1 1 : struct hiyohiyo ( int fumifumi[20] ; 2 : 3 : char takoika; 4 : ) src[10]; 5 : 6 : void f00 ( ) 8 : struct hiyohiyo huge *p; 9 : 10 : p->takoika = 0 : 11 : } 3 ) 。 basedfi インタ * (seg 十 Off) なお , このようなポインタを用いる場合 , 確かに IM バイトのメモリ空間をアクセスて、 きるが , セグメントをまたぐ とが不可能 なこと , すなわち , あくまて、 64K バイト以内 の操作にかぎることに注意が必要て、ある。 したがって , VRAM の操作や , EMS バッフ アの操作などに適しているて、あろう。 p = src , mov word ptr [bp-2] , ds mov word ptr [bp-4] , offset DGROUP src p->takoika : 0 : mov dx, word ptr [bp-2] mov ax, word ptr [bp-4] p->takoika ニ 0 , アドレス計算のために内部関数を呼び出す XO 「 CX, CX mov bx, 40 call near ptr N PADD@ ー OV bX, ax ー OV es, dx 0 を代入する Cbx] , 0 mov byte ptr es . EMS, プロテクトメモリの活用 EMS やプロテクトメモリを活用するひと つの方法として , Turbo C 十十 , Borland C 十十のオーバレイマネージャ VROOMM (Virtual Runtime Object-Oriented Mem oryManager) という機構に触れておこう (Fig. 4 ) 。メモリに入り切らない大きなプロ グラムをオーノヾレイモシュールに分割して , 38 C MAGAZINE 1991 12
Fig. 5 DOS 工クステンダ使用時のメモリ空間 Fig. 4 Turbo C 十十 VROOMM によるメモリマップ CODE クラス 非オーバレイコード領域 OVR 爪 FO クラス オーバレイ制御データ STUBSEG クラス オーバレイスタフ領域 DATA クラス静的領域 nea 「ヒープ領域 スタック領域 0000000 MS-DOS DOS 工クステンダ 空き領域 システム領域 プロテクトモード プログラム MS ー DOS て利用可能なのは このメモリ空間のみ 00A0000 0100000 ↓ ↑ DOS 工クステンダによって 利用可能になるメモリ空間 オーバーレイバッファ オーバーレイモジュールは ここにロードされる fat ヒープ領域 EMS メモリ プロテクトメモリ ← ティスク 0F00000 ↓ Medium モテルの場合 び出し規約て、あることを宣言しなくてはな に示す。冒頭部分て、 , 呼び出し側の DS レジ はこの情報を用いてメモリを管理してい らない スタの値と , BP レジスタ十 1 の値をスタック る。 long FAR PASCAL MyWinProc(HWN 上に保存していることがわかる。 Windows 以上の機能を持つ C コンパイラには , MS D, WORD, WORD, LONG) ; lSt PASCAL 呼び出し規約 PASCAL 呼び出し規約は C 言語の方法と 比べてコードが小さくなり高速になる。 W indows のプログラム自体 , PASCAL 呼び出 し規約にしたことて、 , 大きさが 1 割弱小さく なったということて、ある。 far 関数と fari*—タは , 64K バイトセグメ ントを超えたメモリアクセスを指定する。 Windows のライプラリ関数は別セグメント にあるのて、 , far 呼び出しをしなければなら ない。データポインタも far ポインタによっ て示す必要がある。 そのうえ , far 関数の初めの部分に , 動的 なメモリ管理のための特別なコードを付加 する必要がある。とくに何もしない far ・ P ASCAL 関数をコンパイルした結果を List 3 40 C MAGAZINE 1991 12 (a) ソース void pascal foo(int, int) : foo(), 2 ) ; (c) C 言語呼び出し (Turbo C の場合 ) MOVE AX, 2 PUSH AX MOVE AX, 1 PUSH AX CALL FAR PTR ー f00 POP CX : スタックを元に戻す。 POP CX : 同上 (b) PASCAL 呼び出し規約 MOV AX,I ; 引数を左から積む PUSH AX MOV AX, 2 : PUSH AX CALL FAR PTR ー f00 : スタックは , 関数 f00 の最後の 命令 RET 4 によって戻される。
A 新 IC 言ロロ 明解 柴田望洋 初級 9 級 8 級 7 級 6 級 5 級 4 級 3 級 2 級 1 級初段 2 段 く第 9 回〉構造体と共用体 前回までの内容は正しく理解できましたか。今回は , ポインタとともに C 言語の難 関のひとつであるといわれる構造体の解説をします。構造体は , その必要性や本質 を理解すれば , それほど難しいものではありません。しつかりと勉強しましよう。 List 整数のソート 並びかえ 1 : #include 2 : 3 : #define MAX 4 : 5 : void swap(int *x, int *y) i nt temp : 7 : 9 : temp = *x; 10 : 11 : *y = temp; 12 : ) 13 : 14 : void sort(int data ロ , int n) 15 : { int k = n-l; while (k 〉 = の { int i, j for ( i = 1 : i ← k : i + + ) if (dataCi-1] > dataCi]) { 20 : 21 : 1 J swap(&dataCi], &data[j]) ; 22 : 23 : 24 : 25 : 26 : } 28 : int main(void) 29 : { int i; 30 : 32 : sort(height, MAX) : 33 : for (i = 0 ; i く MAX; i + + ) 34 : printf( ” X4d", heightCi]) ; 35 : return( の ; 36 : く stdio. h> 5 第 5 回 ( 8 月号 ) のポインタの解説時に , 実在 する 5 人の学生に登場してもらいました。 の 5 人を身長順に並べましよう。データの集 まりを昇順・降順などのある一定の規則に 従って並びかえる操作をソーティングとい います ( 通常は単にソートと呼びます ) 。 ソートを行うアルゴリズムは数多く考案 されています。 List 1 に示したプログラム は , 一般にバブルソートという名て、知られ ている , 有名かっ低効率 ( 誉 ; ) のアルゴリ ズムて、す。隣り合うデータの大小関係を比 , 必要ならば交換するという作業を繰り 返すことて、 , データを並び替えます。この バブルソートについては , 過去に本誌のほ かの記事て、も取り上げられたこともあるの て、 ( 多くの市販テキストて、も解説されていま す ) , 誌面の都合上 , 詳細な解説は省略しま す。 こて、 5 ~ 12 行目の swap 関数がポインタ x, y の指す整数の値を交換する関数て、ある ことはわかるて、しよう。 データも用意して , いっしょに並び替えて さてプログラムを具体的に見ましよう。 表示する必要があります。そこて、作成した名前を格納する文字列の配列てある name を Fig. 1 の List 1 の実行結果を見てくださ プログラムが List 2 て、す。実行結果は Fig. 1 扱うように拡張したため , s 。 rt 関数の引数が い。このような表示て、は , 誰の身長が何 cm ひとつ増えていることに気づきます。 32 行 て、あるかがさつばりわかりません。名前の の List 2 の実行結果になります。 116 C MAGAZINE 1991 12 int height ロ = { 178 , 175 , 173 , 165 , 179 } ; 入門講座
今回は , ひさしぶりに整列アルゴリズム を取り上げます。この連載て、は , 第 9 ~ 11 回 の 3 回に渡って整列アルゴリズムを勉強しま 列アルゴリズムの おさらい マージソート ( 第 11 回 : ' 91 年 6 月号 ) クイックソート ( 第 10 回 : ' 91 年 5 月号 ) バブル・選択・挿入ソート 、 0 ( 第 9 回 : ' 91 年 3 月号 ) 78 C MAGAZINE 1991 12 これに対して②は , キーが持っ特別な性 ます。 ズムは存在しないことが明らかにされてい (n 10g n) になり , これより高速なアルゴリ するアルゴリズムて、は , 計算量は最善て、 O 計算量を n の関数て、現します。①に属 ズムて、は , 整列する要素の個数を n として , として整列を行うものて、す。整列アルゴリ ズムて、大小関係が定義されている型をキー の二種類があります。①は汎用のアルゴリ ②キーの特別な性質を利用するもの ①キーの大小比較を利用するもの ゴリズムには , 質について復習してみましよう。整列アル 本題に入る前に , 整列アルゴリズムの性 アルリスム 12 : ) 近藤嘉雪 タ構造を利用して , 常に 0 ( n log n ) の計算量 配列上に半順序木を実現するヒープというテー 整列を行うヒープソートです。ヒープソートは , 取り上けます。今回紹介するのは木を利用して 今回から 2 回に渡って再び整列アルゴリズムを く第 15 回〉ヒープソート テータ構造入門 で整列を行うアルゴリズムです。 質 ( たとえば , キーは 0 以上 10 , 000 以下の整 数て、ある ) を利用するものて、 , うまくすれば 計算量 O ( n ) て、整列を行うことがて、きます。 ただし , いって、も利用て、きるというわけて、 はなくキーがある条件を満たすときに限っ て使うことがて、きます。 これまて、に紹介したアルゴリズムはすべ て①に属するものて、した。また , これらの アルゴリズムは , データの並びに注目して 整列処理を行います。つまり , データを配 列や連結リストの形式て、保持しながら整列 処理を行うわけて、す。 データが一列に並んて、いることを忘れて , ①の範囲内て、別の原理から整列を行うこと がて、きないかを考えてみましよう。②につ いては次回て、取り上げます。 探索木と整列 素を削除して , それを返すというものて、す。 という操作は , その時点て、キーが最小の要 し配列にセットしていきます。 delete min てすべての要素をキーが小さい順に取り出 の要素を登録して , 次に delete min を使っ ケッチは , まず最初に insert によってすべて というふたつの操作を使います。 List 1 のス (delete min) キーか最小のデータを取り出す 要素を挿入する (insert) こて、は , List 1 のようになります。 アを検討してみましよう。アルゴリズムは 探索を利用して整列を行うというアイデ 探索木を利用した整列アルゴリズムのスケッチ 3 : 4 : 5 : 6 : 7 : 8 : 9 : 10 : 11 : List 1 int n) 1 : sort(int a[], int i; / * すべての要素を探索木に挿入する。 for (i = 0 ; i く n; i + + ) insert(a[i)); / * 要素をキーが小さい順に取り出す。 for (i 0 : i く n; i + + ) aCi] : delete-min();