• 検索結果がありません。

復習 C コンパイラについて

ドキュメント内 新潟大学学術リポジトリ (ページ 54-60)

• 実習室の計算機ではC言語のコンパイラが1種類だけ用意されています。コンパイラ を起動するためのコマンドとしてgccと cc の2つが用意されていますが、これらの 実体は同じです。(他に c99-gcc 等もありますが、これらは特殊なオプション付きの gcc の様です。)

motoki@ap1:~$ which gcc /usr/bin/gcc

motoki@ap1:~$ ls -l /usr/bin |grep cc (省略)

-rwxr-xr-x 1 root root 428 6 13 2013 c89-gcc -rwxr-xr-x 1 root root 454 6 13 2013 c99-gcc

lrwxrwxrwx 1 root root 20 2 23 2015 cc -> /etc/alternatives/cc (省略)

2.5. 復習 Cコンパイラについて 49

motoki@ap1:~/C-java$ script report.log Enter

...ログファイル report.log への記録を開始 Script started, file is report.log

motoki@ap1:~/C-java$ cat lab-ex01-ceiling.c Enter

#include <stdio.h>

int main(void) {

int x, y, sum, ceiling;

scanf("%d %d", &x, &y);

sum = x + y;

ceiling = x/y + (x%y + y - 1)/y; /* x/y の小数点以下切り上げ */

printf("%d+%d=%d\n", x, y, sum);

printf("ceiling(%d/%d)=%d\n", x, y, ceiling);

reurn 0;

}

motoki@ap1:~/C-java$ gcc lab-ex01-ceiling.c Enter motoki@ap1:~/C-java$ ./a.out Enter

8 3 Enter 8+3=11

ceiling(8/3)=3

motoki@ap1:~/C-java$ ./a.out Enter 999 3 Enter

999+3=1002

ceiling(999/3)=333

motoki@ap1:~/C-java$ exit Enter ...ログファイルへの記録を終了 exit

Script done, file is report.log motoki@ap1:~/C-java$

図 1: scriptコマンドを用いて会話の様子を report.logに記録

Script started on 20160307 171133

^[]0;motoki@ap1: ~/C-java^Gmotoki@ap1:~/C-java$ cat lab-ex01-ceiling.c^M

#include <stdio.h>^M

^M

int main(void)^M {^M

int x, y, sum, ceiling;^M

^M

scanf("%d %d", &x, &y);^M sum = x+y;^M

ceiling = x/y + (x%y + y - 1)/y; /* x/y の小数点以下切り上げ */^M printf("%d+%d=%d\n", x, y, sum);^M

printf("ceiling(%d/%d)=%d\n", x, y, ceiling);^M return 0;^M

}^M

^[]0;motoki@ap1: ~/C-java^Gmotoki@ap1:~/C-java$ gcc lab-ex01-ceiling.c^M

^[]0;motoki@ap1: ~/C-java^Gmotoki@ap1:~/C-java$ ./a.out^M 8 3^M

8+3=11^M

ceiling(8/3)=3^M

^[]0;motoki@ap1: ~/C-java^Gmotoki@ap1:~/C-java$ ./a.out^M 999 3^M

999+3=1002^M

ceiling(999/3)=333^M

^[]0;motoki@ap1: ~/C-java^Gmotoki@ap1:~/C-java$ exit^M exit^M

Script done on 20160307 171303

図 2: ログファイルの中身(生成直後,emacsで表示)

2.5. 復習 Cコンパイラについて 51

lrwxrwxrwx 1 root root 7 2 25 2015 gcc -> gcc-4.9 -rwxr-xr-x 1 root root 353752 11 28 2012 gcc-4.6

-rwxr-xr-x 1 root root 832120 12 26 2014 gcc-4.9 (省略)

motoki@ap1:~$ ls -l /etc/alternatives/cc

lrwxrwxrwx 1 root root 12 2 23 2015 /etc/alternatives/cc -> /usr/bin/gcc motoki@ap1:~$

• 以下は、Cコンパイラについての一般的なお話です。Cプログラミングの際の参考に して下さい。[cc と gcc に共通した話です。]

ccコマンド/gccコマンドによるCプログラムの翻訳作業は、次に示される様に前1 処理,コンパイル,2 最適化,3 アセンブリ,4 リンク&ロード,という5 5段階の処理 を経て行われる。 [実際の処理プログラムの名前, 配置ディレクトリはシステムによって 異なるかも知れませんが、処理の大きな流れは同じです。]

Cのソースファイル .c

前処理プログラム1 /usr/local/lib/gcc-lib/· · ·/cpp . . . .

ヘッダファイルの取り込 み,マクロの展開,注釈の 除去などを行う。

#で始まる行(e.g. #include行, #define行)や 注釈を含まないCのソースプログラム .i

コンパイラの本体2 /usr/local/lib/gcc-lib/· · ·/ccl . . . .

"

構文解析, 意味解析等は ここで行う。

アセンブリプログラム .s . . . .

"

機械語プログラムの命令語、アドレス 等を記号表記したもの。

最適化プログラム3 (/usr/· · ·??) . . . .

"

-Oオプションが指定された時は、実行 速度, コードの大きさの改善を図る。

アセンブリプログラム .s . . . .

"

-Sオプションの指定があればこのアセ ンブリプログラムも保存される。

アセンブラ4 /usr/ccs/bin/as

オブジェクトプログラム

(のファイル) .o . . . .

2進コードと再配置情報が入っている。

-cオプションの指定があったりソース ファイルが2個以上あったりするとファ イルが残る。

リンカ5 & ローダ/usr/ccs/bin/ld . . . .

複数のオブジェクトファイルをまとめ る。その際、必要なライブラリ関数の コードも取り込む。

実行形式プログラムのファイル . . . [-oオプションの指定がなければa.out

これら5段階の動作を制御するために、ccコマンド/gccコマンドには様々なオプショ ンが用意されています。 例えば gccコマンドについては次の通り。

形式:

gcc

[ options ] files [-l library ]

options: -c : オブジェクトファイルだけを生成し、リンカ&ローダを

呼び出さない。

-g : デバッガのための特別なシンボル表もコンパイルの際 に生成し、リンカ&ローダld に -lg オプションを引き 渡す。

-o ファイル名 : 実行形式プログラムを入れるファイルを a.out ではな くファイル名 とする。

-O : 最適化を行う。

-D 名前 = 定義 -U 名前

-I パス名 -P

-S -v -p -pg

.. .

(説明省略)

-l library: -lx : リンカ&ローダにこのオプションをそのまま引き渡し、

オブジェクトプログラムをまとめ上げる際、必要に応 じてライブラリ(アーカイブファイル) libx.a 内の関数

(オブジェクトコード)を用いることを指示する。 12個

のヘッダファイル<assert.h>, <ctype.h>, <float.h>,

<limits.h>, <setjmp.h>, <signal.h>, <stdarg.h>,

<stdio.h>, <stdlib.h>, <string.h>, <time.h> 内で 宣言された関数はANSI標準で、/lib/libc.a というライ

ブラリ(アーカイブファイル)にまとめられている。この

標準ライブラリに関する-lcというオプションはcc コ マンドに付加しなくても自動的にリンカ&ローダに引き 渡されるが、数学ライブラリ関数はANSI標準でないた め、数学関数を用いた場合は数学ライブラリ/lib/libm.a の使用をリンカ&ローダに申告するための-lmオプショ ンを cc コマンドの最後に付加しなければならない。付 加しないと「undefined symbol (未定義の記号がある)」

というエラーになる。

詳しくは、man gcc でオンラインマニュアルを調べるなり、次の図書を見るなりして下 さい。

• 山口和紀&古瀬一隆(監),新The UNIX SuperText下 改訂増補版, 技術評論社, 2003.

2.5. 復習 Cコンパイラについて 53

• P.S.Wang, ANSI C & UNIX 下, 共立出版, 1994.

例えばprog.c というCプログラムがある時、% gcc -g prog.c -lm とコマンド入力 すると計算機内部では次の様な処理が行われます。

prog.c

前処理プログラム1 /usr/local/lib/gcc-lib/· · ·/cpp コンパイラの本体2 /usr/local/lib/gcc-lib/· · ·/ccl アセンブラ4 /usr/ccs/bin/as

prog.o . . . .次のステップ「5リンカ&ローダ」の後で削除される。

リンカ&ローダ5 /usr/bin/ld /usr/ccs/lib/crt1.o prog.o -lg -lm -lc オブジェクトプログラムの並び。左から右に見て行っր た時、未定義の記号は後方で必ず処理される様に並べ ないといけない。[ここで、/usr/ccs/lib/crt1.o は初 期化を行ったり関数mainを呼び出したりするCのス タートアップルーチンである。]

⇓ a.out

演習問題

□演習 2.1 (プログラム作成・修正・保存・実行) この講義ノートの第1章, 参考書など

から練習問題をいくつか選んで、Cプログラムのコンパイル/実行/デバッグを行って みよ。 その際、プログラムを故意に間違えて、どんなエラーメッセージが出るか試して みよ。

□演習 2.2 (sttyコマンド;読み飛ばし可) stty -aとコマンド入力して、どの特殊機能 がどのキーに割り当てられているかを調べてみて下さい。

3 復習 処理の選択と繰り返し

3つの数の最大値(if文,if-else構文,論理演算, 条件演算子),

階乗 (for文), どうやって繰り返し構造を見出 すか?,

自習 素数(break文),最大公約数(ユークリッ ドの互除法),

自習 不定個の入力データの合計(while文),

自習 元号表記→西暦表記(switch文),

自習 プログラムを組み立てられない時は...

この節では、下図の形の処理の流れがC言語でどの様に記述されるのかを見る。

True

False

True False

True

False False

False True

True ・・・

・・・ ・・・

True False

True False

True False

入力

True False 入力失敗

ドキュメント内 新潟大学学術リポジトリ (ページ 54-60)