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

第 7 章 言語処理系 172

7.3 C

実行すると,“Hello, C world!”という文字列がターミナルに表示されます.

gccコマンドでオプションを指定せずにコンパイルを行うと,前述のようにa.outという名前の 実行ファイルが出力されます.これを任意の名前に変えるためには,gccの“-o”オプションを使用 します.例えば,helloという実行ファイルを出力したい場合,以下のようにします.

$ gcc -o hello test .c

7.3.2 ヘッダファイル,ライブラリ

先ほどのプログラムでは,プログラム内で文字列を出力するためにprintf関数が使われていま す.この関数を用いるために,printf関数が宣言されているstdio.hという名前のファイルをイン クルードしています.このようなファイルをヘッダファイル(Header File)と言います.

また,関数の宣言に対応する関数の実体は,ライブラリファイル(Library File)と呼ばれるファ イルの中に存在します.ライブラリファイルは,コンパイル時に結合する必要があり,このことを

リンク(Link)すると言います.標準的なライブラリファイルは自動的にコンパイル時にリンクさ

れますが,そうではないライブラリは明示的に指定する必要があります.これについては,7.3.10 節で詳しく説明をします.

どの関数がどのインクルードファイルに宣言されているかを調べるためには,manコマンドを 使ってマニュアルで調べます.調べるときには,シェルから“man (関数名)”と実行します.また,

このマニュアルの中では,関数の使い方や関数の引数,オプション,注意などが載っていますので,

関数を使うときにはこのマニュアルを見るようにしましょう.

例えば,sqrt関数のmanを開くと,マニュアルに以下のように載っています.書式の部分では,

関数の戻り値,引数などが書いてあります.説明の部分では,この関数の使い方などが書いてあり ます.バグの部分では,関数を使う際の注意が書いてあるので,注意が必要です.

sqrt関数のman

SQRT(3) BSD Library Functions Manual SQRT(3)

NAME

sqrt -- square root function

SYNOPSIS

#include <math.h>

double

sqrt(double x);

long double

sqrtl(long double x);

float

sqrtf(float x);

DESCRIPTION

The sqrt() function compute the non-negative square root of x.

SPECIAL VALUES

sqrt(-0) returns -0.

sqrt(x) returns a NaN and generates a domain error for x < 0.

SEE ALSO math(3)

STANDARDS

The sqrt() function conforms to ISO/IEC 9899:1999(E).

BSD December 11, 2006 BSD

7.3.3 参考になる資料

man gcc

ハーバート・シルト著, 柏原 正三 監修「独習C」(翔泳社)

B.W.カーニハン/D.M.リッチー著 石田晴久訳「プログラミング言語C(第2版)ANSI規 格準拠」(共立出版)

7.3.4 デバッグ

7.3.5 printf を使った簡単なデバッグ

ここでは,Cプログラムのデバッグについて説明します.デバッグ(Debug)とは,プログラム の不具合(バグ)を修正することです.簡単なデバッグの方法としては,ソースコード中にデバッ グ情報の出力を埋め込む方法があります.

簡単にできるデバッグの方法として,printfを使ってプログラム中で使用している変数などの情 報を出力する方法があります.これは単にプログラム中でprintf関数を使って変数の中身を表示 するだけですが,簡単にできます.しかし,この方法だとデバッグ情報を出力する部分がプログラ ム中に埋め込まれてしまい,デバッグが終わった後にデバッグ情報の出力部分をコメントアウトす る手間がかかります.

そこで,#ifdef文を用いてデバッグの時とそうでない時で,プログラムのコードを切替えられる

ようにします.これにより,デバッグの時だけ,デバッグ情報を出力することが可能になります.

次のプログラムは,#ifdef文を使ってプログラムを切替えられるようにしたものです.

Listing 7.5: test debug.c

1 # include< stdio .h >

2

3 int main ()

4 {

5 printf (" Hello ,␣C␣ world !\ n");

6 # ifdef DEBUG

7 printf (" This ␣ is ␣ debug .\ n");

8 # endif

9 return 0;

10 }

test debug.cはtest.cの6行目〜8行目に#ifdef文を使ったプログラムを追加したものです.

“#ifdef (マクロ名) 〜#endif”にはさまれた部分は,(マクロ名)が定義されているとコンパイル の対象になります.もし,マクロが定義されていない場合,この部分はコンパイル時に無視されま す.つまり,コンパイル時にマクロを定義することで,デバッグ用のプログラムを生成することが できます.

マクロを定義する方法には,#defineをソースファイル中に定義する方法とコンパイル時にコン パイラのオプションで指定する方法があります.このうち,コンパイル時にマクロを指定するに は,コンパイルオプションに“-D(マクロ名)”と指定します.

$ gcc -o test \ _debug test \ _debug .c - DDEBUG

$ ./ test \ _debug Hello , C world ! This is debug .

$ gcc -o test \ _debug test \ _debug .c

$ ./ test \ _debug

Hello , C world !

7.3.6 デバッガの利用

デバッガ(Debugger)というデバッグをサポートするためのプログラムを使うことで,効率的に

デバッグを行うことができます.ここでは,上記2つの方法をそれぞれ説明します.

printfを使ったデバッグの方法について説明しましたが,この方法では,デバッグしたい箇所に

全部のデバッグ情報を書かなければなりません.また,短いプログラムの場合,ソースコードを見 ているだけでも簡単にバグを発見することができますが,ソースプログラムが長く,複雑になる と,バグを見つけることが難しくなってきます.

そこで,デバッガというデバッグをサポートするツールを使います.一般的なデバッガでは,プ ログラムを途中で止めて変数の中身を見たり,1行ごとにプログラムを実行したりすることができ ます.これにより,非常に効率良くデバッグを行うことができます.例えば,課題のプログラムな どでバグがどこにあるかわからなくなったら,デバッガを使ってデバッグすることで,バグを見つ けることができるかもしれません.

ここでは,次の簡単な剰余計算を行うプログラムをデバッグするとします.デバッガには,gdb

(GNUデバッガ)を使用します.

Listing 7.6: test gdb.c

1 # include < stdio .h >

2

3 int mymod (int i , int j) {

4 while(i >= j)

5 i -= j;

6 return i;

7 }

8

9 int main () {

10 int x = 20 ,y = 3;

11 printf ("%d␣( mod ␣%d)␣=␣%d\n",x ,y , mymod (x ,y));

12 return 0;

13 }

デバッガを利用するためには,コンパイル時にデバッグに必要な情報をプログラムに埋め込んで おく必要があります.そのためには,gccに“-g”オプションをつけてソースコードをコンパイルし ます.

$ gcc -o test_gdb test_gdb .c -g

このようにして実行ファイルを生成するとgdbを利用してデバッグを行うことができます.

次に,gdbコマンドを使って,gdbを起動させます.引数には,実行するファイルのファイル名 を指定します.

$ gdb test_gdb

起動すると,以下のように表示されます.ここから,コマンドでデバッガを操作します.