プログラミング演習I

プログラミング演習II
2004年10月26日(第2回)
理学部数学科・木村巌
前回までの復習





ローカル変数
グローバル変数
変数の可視範囲
変数の寿命
staticなローカル変数
今日学ぶこと






関数の宣言
複数のファイルからなるプログラムを作成で
きるようになる
複数のファイルからなるプログラムでのス
コープを理解する
標準ライブラリ関数とは何かを理解する
標準ライブラリ関数の使い方を身につける
教科書8.8から(p. 261~)
関数の宣言

関数プロトタイプ宣言



関数の名前、引数の数、引数の型、返値の型を
コンパイラに知らせる
コンパイラは、コンパイル時にこれらをチェックで
きる(静的な検査)
構文
戻り値の型 関数名 (引数リスト);
 最後のセミコロンを忘れないこと

Sample12.cを入力して、コンパイル・実行して
みよう
ファイルを分割する



関数プロトタイプ宣言は、複数のファイルから
なるプログラムの作成に特に有効
他のプログラムでも作成するような関数は、
用途別に別のファイルにしておく
その関数のプロトタイプ宣言も、いわゆる
「ヘッダーファイル」に別に記述しておく
複数ファイルからなるプログラムの例



myfunc.h, myfunc.c, Sample13.c (p.264)を入
力し、コンパイル、実行してみよう
(次のスライド参照)
コンパイル・リンク・オブジェクトファイルといっ
た専門用語については、前期の4/28の回の
スライドを参照
コンパイルの仕方


コンパイルの仕方:二通りある
一気に実行ファイルを作成する


gcc –o Sample13 Sample13.c myfunc.c
一旦オブジェクトファイルを作り、それらをリン
クする



gcc –c Sample13.c
gcc –c myfunc.c
gcc –o Sample13 Sample13.o myfunc.o
コンパイルの仕方(続き)


一度オブジェクトファイルを作ると、変更を加
えなかった方は、コンパイルし直さなくてもよ
い
例:Sample13.cは変更したが、myfunc.cは変
更していない場合:


gcc –o Sample13 Sample13.c myfunc.o
巨大なプログラムの場合、コンパイルするだ
けで何時間もかかることがある
標準ライブラリ関数の仕組みを知る

標準ライブラリ関数




C言語の規格で定められている、基本的な処理
(入出力、文字列操作など)を行うための関数
どのCコンパイラにも付属している
例:printf(), scanf()などなど
標準ライブラリ関数のプロトタイプ宣言


それぞれ記述されているヘッダファイルが定めら
れている
例:printf()ならstdio.h のように
ヘッダファイルの指定

標準のヘッダファイルの読み込み


#include <stdio.h>のように、<>で指示する
自分で作成したヘッダファイルの読み込み

#include “myfunc.h” のように、””で指示する
標準ライブラリ関数はどこにあるの
か?




標準ライブラリ関数の実体は、/usr/bin/libc.a
という、スタティックライブラリに含まれている
複数のオブジェクトファイルを、ひとつのアー
カイブファイル(archive file)にまとめる事がで
きる
リンク時に、リンカが必要な関数を取り出して、
実行ファイルにまとめる
ar –t /usr/lib/libc.a で、libc.a内のオブジェクト
ファイル一覧を見ることができる
ライブラリを作ってみる






myfunc1.c と myfunc2.c を作る。それぞれ、
void myfunc1(void){}, void myfunc2(void){}
のみ含むことにする
gcc –c myfunc1.c
gcc –c myfunc2.c
これで、myfunc1.oとmyfunc2.oができる
ar –q libmyfunc.a myfunc1.o myfunc2.o
これで、libmyfunc.a というアーカイブができる
ライブラリを使ってみる





main.c というファイルに、main()を書いておく
main()内で、myfunc1(), myfunc2()を呼び出す
gcc –o main main.exe –L. –lmyfunc
これで、main.exeができる
main.exe には、libmyfunc.aから、myfunc1()
とmyfunc2()がリンクされる
複数のファイルからなる
プログラムでのスコープ





識別子がプログラムの全域で可視:「外部リ
ンケージを持つ」という
識別子が、宣言されたファイルでのみ可視:
「内部リンケージを持つ」という
外部リンケージを持つのは:関数名、グロー
バル変数名
内部リンケージを持つのは:それ以外
例外あり(次のスライド)
複数のファイルからなる
プログラムでのスコープ(続き)


staticをつけた関数名は、内部リンケージを持
つ
変数名に付けるstatic(変数の寿命の指定)と
は、意味がまったく異なるので、注意
グローバル変数は乱用しない




グローバル変数:プログラムの全体から読み
書き可能
使い方を誤ると、厄介なバグ(bug, プログラム
の不具合)を招く
プログラムのどの箇所で変更されたのか、追
跡しづらい
絶対に必要な場合にしか使わないこと
自作のライブラリを作る場合



ライブラリのユーザにとって、簡便で、使いや
すいライブラリになることを目指す
不必要な関数は、staticにして、内部リンケー
ジを持たせる
必要な関数のみ、ヘッダファイルに記述して、
プログラムから使えるようにする
今日学んだこと





関数の宣言
複数のファイルからなるプログラム
複数のファイルからなるプログラムでのス
コープ
標準ライブラリ関数とは何か
標準ライブラリ関数の使い方
レポート課題




与えられたlongが素数なら1, そうでないなら0を返
す関数int isprime (long p)を含むisprime.c, そのプ
ロトタイプ宣言を含むisprime.h, main()関数を含む
main.cをそれぞれ作成せよ.main()を実行すると、
整数を入力するよう促し、素数であるか、そうでな
いかを表示すること.
締め切り:2004年11月1日一杯(日本時間で)
提出:メールで木村([email protected])まで.
感想などあると木村が喜びます
レポートのヒント
int isprime (long p) ; /* プロトタイプ宣言 */
int isprime (long p) { … } /* 関数の定義 */
 main.cでは
#include <stdio.h>
#include “isprime.h”
int main (void) { … }