• 実習室の計算機ではC言語のコンパイラが1種類だけ用意されています。コンパイラ を起動するためのコマンドとしてgccと cc の2つが用意されていますが、これらの 実体は同じです。(他に c99-gcc 等もありますが、これらは特殊なオプション付きの gcc の様です。)
motoki@ap1:~$ which gcc
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に記録
50 2. 実習案内 Cプログラミング環境
Script started on 2016年03月07日 17時11分33秒
^[]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 2016年03月07日 17時13分03秒
図 2: ログファイルの中身(生成直後,emacsで表示)
2.5. 復習 Cコンパイラについて 51
/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 (省略)
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個以上あったりするとファ イルが残る。
52 2. 実習案内 Cプログラミング環境
⇓
リンカ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標準でないた
2.5. 復習 Cコンパイラについて 53
め、数学関数を用いた場合は数学ライブラリ/lib/libm.a の使用をリンカ&ローダに申告するための-lm オプショ ンをcc コマンドの最後に付加しなければならない。付 加しないと「undefined symbol(未定義の記号がある)」
というエラーになる。
詳しくは、man gcc でオンラインマニュアルを調べるなり、次の図書を見るなりして下 さい。
• 山口和紀&古瀬一隆(監),新The UNIX SuperText下 改訂増補版, 技術評論社, 2003.
• 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とコマンド入力して、どの特殊機能 がどのキーに割り当てられているかを調べてみて下さい。
54 3. 復習 処理の選択と繰り返し
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 入力失敗