Cプログラマへの初めの一歩

最終更新日: 2005/02/16

目次

  1. プログラミングとは
  2. 開発環境を構築する
  3. gccを使ってみる
  4. C言語を学ぶには
  5. Appendix A. データの視覚化
  6. Appendix B. デバッガの使用法
  7. 更新履歴

1. プログラムとは

プログラムとは、コンピュータに指示を出すことです。

しかし、人間が指示を記述しやすい言語(ソースコード)と、コンピュータが理解しやすい言語(機械語)は必ずしも一致しないため、一般に翻訳(コンパイル)が必要になります。コンピュータに何かを実行させたい場合は、下図のように指示を記述したソースコードを書き、それをコンパイルして得られた機械語でコンピュータに指示を与えます。
プログラミングを始めるために必要な道具はエディタとコンパイラです。次の節で準備方法を解説します。

(コンパイラを使用しない方法としては、ソースコードを一気に機械語に"翻訳"するのではなく、逐次機械語に"通訳"する手法があります。この通訳はインタープリタと呼ばれています。また、その気になればCPUの仕様書片手にいきなり機械語で書くことも可能です。きっとCPUの気持ちが分かるでしょう。)

2. 開発環境を構築する

この章ではWindowsとMac OS Xを対象にC言語の開発環境を構築する方法を説明します。

Windows 95/98/Me, 2000/XP

Windows用のCコンパイラは数多くありますが、ここでは最も広範囲で使用されているgccを選ぶことにします。

1回生の講義でUnixの使い方を習っているらしいので、Cygwin上でgccを使うことにします。
Cygwinとは、gccをはじめUnixの様々なツールをWindowsで動作できるようにするものです。
では早速Cygwinのインストールを順を追って説明しましょう。(参考サイト:Cygwinを使う)

  1. まずRedHatからインストーラ(setup.exe)をダウンロードします。
  2. Cドライブに"tmp"というフォルダを作り、その中に"cygwin"というフォルダを作ります。
  3. 作成したフォルダ(C:¥tmp¥cygwin)の中にダウンロードしたインストーラ(setup.exe)を移動します。
    (理由: 後で分かるがLocal Package Directory(デフォルトはsetup.exeのあるフォルダ)には、日本語やスペースの入ったパスが指定できないため)


  4. インストーラを起動します。
  5. 下のSelect Packagesの画面になるまで、デフォルトボタン(次へボタン)を押します。


  6. Categoryリスト中にDevel Defaultがあるので、Defaultを1回クリックしInstallに変えます。
    Develパッケージにはgccが含まれています。他にもインストールしたい項目があれば同様にInstallに変えます。
    インストールする項目が決まったら、"次へ"ボタンを押ししばらく待ちます。
    最後に"完了"ボタンを押してインストーラでの作業は終了です。


  7. Cygwinを起動する前に環境変数を設定します。
    Cドライブのファイルシステムによって環境変数の設定が異なるので、まずファイルシステムが何であるか確認します。
    ファイルシステムは下図のように、Cドライブを右クリックし"プロパティ"を選択すると開くウィンドウの"全般"タブから確認できます。



    ここではWindows XP/2000での設定方法について説明します。
    Windows 95/98/Meでの設定方法はこちらのページを参照してください。
    "マイ コンピュータ"を右クリックしプロパティを選択し、"詳細"タブの"環境変数"ボタンを押します。
    ユーザー環境変数に次の4個を新規登録します。usernameの箇所は好きなユーザー名(アルファベット)にしてください。
    CYGWINの設定はファイルシステムがNTFSかどうかで違うので注意してください。

    変数名変数値
    HOME/home/username
    MAKE_MODEUNIX
    SHELL/bin/bash
    CYGWINntsec (NTFSの場合)または、nontsec (NTFS以外(FAT32等)の場合)


  8. 最後にCygwin用のホームディレクトリを作ります。
    Cドライブのcygwinフォルダを開きます (C:¥tmp¥cygwinではなく、C:¥cygwinの方です。)。
    新規フォルダを作成し名前をhomeにします。
    homeフォルダの中に先ほどのusernameと同名のフォルダを作ります。(デスクトップにこのフォルダのショートカットを置いておくと便利でしょう。)
    これでCygwinのインストール作業はすべて完了です。


  9. プログラミング作業の大部分はソースコードの読み書きなので、使用するエディタがC言語の編集に適しているかどうかが作業効率に大きく影響を与えます。
    適していると思われるフリーのエディタではTeraPadサクラエディタがお勧めです。
    もちろんCygwin上でemacs等を使用するのもいいでしょう。

Mac OS X

Mac OS XはUNIXなのでDeveloper Toolsをインストールしておしまいです。

エディタはDeveloper ToolsのXcodeやSubEthaEditがお勧めです。
もちろんX11やterminalでemacsを使用する選択肢もあります。

3. gccを使ってみる

動作テスト用ソースコードhello.cをダウンロードします。
hello.cをホームディレクトリ(Windowsでは先ほど作ったC:¥cygwin¥home¥usernameです)に置きます。

WindowsユーザーはCygwinを、MacユーザーはTerminal (/Applications/Utilityの中にあります) を起動します。
次のコマンドでコンパイルします。意味は後で説明します。

gcc -o hello hello.c

Windowsでは hello.exe、Macでは hello というファイルが作られたはずです。
これがコンパイルで作られた実行ファイルです。

では試しに動かしてみましょう。

Windowsでは ./hello.exe、Macでは ./hello というコマンドを入力します。
コンソールに"Hello."と表示されるはずです。

プログラミングは基本的にこのように、ソースコードを書き、コンパイルし、動かしてみるという流れで進みます。
順序どおりこなしていけば難しいことはありません。

gccには様々なオプション機能があります(ありすぎます)が、最低限、次の使い方を覚えておけば良いでしょう。

gcc -o 作りたい実行ファイル名 ソースコード名.c

4. C言語を学ぶには

C言語は誕生してから30年以上経っており、多くの解説書や解説サイトが存在しています。
コンピュータの本は高価なものが多いので、本の内容が評価できる程度まで下記のようなWebで勉強してから自分に合ったもの購入するといいでしょう。

言語自体の習得にはWebで事足りると思います。
プログラムとはアルゴリズムに従ってデータを処理することなので、アルゴリズムを記述する方法と、データ構造について詳しく書かれた本を持っていると役に立つと思います。
個人的にお勧めの本はC言語による最新アルゴリズム事典です。
この本は辞書的な本なので、これ以外に1冊アルゴリズムとデータ構造の教科書的な本を読むといいでしょう。

機械語はコンピュータが実行するものですが、ソースコードを読み書きするのは人間です。
読みやすい書き方を心がけるのが、上達の第一歩だと思います。
プログラミング作法の第1章に読みやすい書き方が解説されているので目を通しておくといいでしょう。

プログラミングの上達の秘訣は良いプログラムを手本にすることです。頑張ってください。

5. プログラムの典型的な構造

世の中には様々なプログラムがありますが、ほとんどのプログラムは大雑把に言って下図のような、何かの「入力」を元に何か「計算」し何かを「出力」するという構造を持っています。例えば次にあげる3つのプログラム例がそうです。

ファイルからのデータの読み込み方法

提出してもらったレポート問題 2-1、2-2で生成した乱数ファイルを分類したところ、大きく3つのタイプに分類できました。

各タイプでのデータ読み込み方法を考えるのに参考となるプログラム用意しました。
この例はファイルから角度データ(倍精度実数)を読み込みサインの値を計算するものです。
このプログラムは数学ライブラリ(math.h)を使用しているので、講義のときに説明したようにコンパイル時に -lm オプション(意味は次節で説明します)を付けてください。
このプログラムのポイントは、34行目と36行目にあるfgets()sscanf()の使い方です。

なお、実行時にデータファイルパスを引数で渡すようになっています。
例えば、タイプ1の実行ファイルをsin1とすると、./sin1 degrees1.txt のように実行してください。

ライブラリの活用法

プログラムを作る際にFourier変換や連立線形方程式の解法といった基本的な関数が必要になることがよくありますが、 必要になるたびに毎回自分で作るのは非効率ですし、既に誰かが作っていることが多いです。
このような汎用的な関数を使いやすい形で提供する手段がC言語にあり、web上でよく公開されています。それがライブラリです。
前節で使用した数学ライブラリ(math.h)がその一例です。sin()等の関数を使用したいソースコードの中でmath.hをincludeし、コンパイル時に-lmオプション(意味は後で説明します)を指定することで使用することができました。

ここではレポート問題5-1を解くために必要なFFTや連立線形方程式の解法を提供するライブラリを例に挙げて説明します。

まずFFTライブラリですが、例えばシンプルなものでは数理研の大浦拓哉氏が作成したFFT(DCT)ライブラリが、高速高機能なものではFFTW (FFTW Tips)があります。
ではFFT(DCT)ライブラリを例にとって、太陽黒点の年次変化のパワースペクトルを求めるプログラム(テキストの問題4-4の[2])を作る場合について考えてみましょう。

  1. まず自分の環境に合わせてライブラリを生成します。
    ライブラリの公開サイトからfftlib.tar.gzをダウンロードし、適当な場所に解凍します。
    次に解凍してできたディレクトリfftlibに移動してmakeを実行します。

    tar xzvf fftlib.tar.gz
    cd fftlib
    make

    コンパイルが終了したらlibfftlib.aというファイルができていることを確認してください。これがライブラリの本体です。
    ライブラリを使用する場合、この本体(libfftlib.a)とインターフェースを記述したファイル(fftlib.h)が必要になります。
  2. プログラムを作成するのに必要なファイルを集めます。
    太陽黒点数の年次変化のパワースペクトルを求めるプログラムのソースコードとデータファイル(ROYAL OBSERVATORY OF BELGIUMのyearly sunspot number)を適当なディレクトリにダウンロードし、そこに先ほど生成したlibfftlib.aとfftlib.hをコピーします。
    spec.cとyearssn.dat、libfftlib.a、fftlib.hの4つのファイルが揃っていることを確認してください。
  3. コンパイルする前にソースコードに目を通しましょう。
    FFTライブラリのおかげで非常に簡単なプログラムになっています。
    ライブラリを使用する宣言(#include "fftlib.h")があることに注意してください。
  4. では、コンパイルしましょう。(-Lの後ろにはドット'.'があります。)

    gcc -o spec spec.c -lm -lfftlib -L.

    ここで現れた-lfftlibオプションの意味は、libfftlib.aをプログラムに結びつける(リンクする)ということです。
    一般に"-l何とか"と書いた場合は"lib何とか.a"をリンクするという意味になります。
    -Lオプションはライブラリを検索する場所の指定です。今の場合、コンパイルを実行するディレクトリにライブラリがあるので、この場へのパス(ドット'.')を指定しています。別の場所にライブラリを置いた場合はその場所へのパスを指定します。
  5. プログラムを実行してみてパワースペクトルを収めたファイル(power_spectrum.txt)が出力されれば成功です。
    (参考: gnuplotでパワースペクトルをプロットしたもの(Δ=1yr, N=256, k=23に強いピークがみられる。このことから周期T=ΔN/k=約11年が分かる)、太陽黒点数の年次変化のプロットしたもの。)
まとめると、ライブラリを使用する場合に注意すべき所は次の3点です

連立線形方程式を解くライブラリについても同様です。
線形代数計算一般を行うライブラリではCLapack(CLapackの使い方)が高機能・高性能で定評がありますが色々と面倒なので、今回は連立線形方程式を解くことだけに的を絞って伊藤昭浩氏作のライブラリ(正確にはライブラリではない)を使用する方法を選びます。

FFTの場合とほぼ同じ説明の繰り返しになります。
ただしFFTの場合と異なって、ダウンロードしたleq.tar.gzを解凍しmakeしてもライブラリは作られません。
そのため、makeを実行した後に次のコマンドでライブラリを作る必要があります。

ar rs libleq.a Gauss.o LU.o Iterations.o equation.o vector.o

実行後にlibleq.aが作られたことを確認してください。このライブラリのインターフェースを記述したファイルはGauss.h、LU.h、Iterations.h、equation.h、vector.hです。

では使用例ソースコードをダウンロードし、同じディレクトリにlibleq.aと5個の.hファイルをコピーし、コンパイル、実行してみてください。
コンパイルは前と同様に

gcc -o solveLeq solveLeq.c -lleq -L.

で行います。

Appendix A. データの視覚化

GNUPLOTを使用すると2次元、3次元データをプロットすることができます。
このAppendixではインストール方法と基本的な命令について説明します。
(ダイアグラムのような関連図を描画するにはGraphviz(解説)が便利です。)

GNUPLOTのインストール (Cygwin用)

GNUPLOTを使用するにはGNUPLOTとX Window System(X11)をインストールする必要があります。
どちらも2. 環境を構築するで使用したCygwinのインストーラ(削除していない場合はC:\tmp\cygwin\setup.exeにあります)からインストールできます。

  1. まずGNUPLOTをインストールします。
    下図のようなパッケージ選択画面になるまで"次へ"ボタンを押し進みます。
    Graphics Categoryの左側にある"+"記号をクリックしグループを開き、サブグループ中のgnuplotを探しマークをクリックし、下図のようにバージョン番号もしくはKeepにします。
    Graphics Categoryの左側にある"+"記号をクリックしグループを閉じます。


  2. 次にX Window Systemをインストールします。
    下図のようにX11 Categoryの右側にあるマークをクリックしInstallに変えます。


  3. これでパッケージ選択は終了です。"次へ"をクリックしインストールを完了させます。

GNUPLOTのインストール (Mac OS X 10.3以降用)

GNUPLOTを使用するにはGNUPLOTとX Window System(X11)をインストールする必要があります。
X Window SystemはOSに標準で付いてくるX11を使用します。
OSのインストーラを使用するかアップルからインストーラをダウンロードしインストールします。
GNUPLOTをインストールするにはfinkというパッケージインストーラを使用するのがいいでしょう。

  1. まず田中俊光氏による解説を参考にしてX11とfinkをインストールします。
  2. 次にFink Commanderを利用しGNUPLOTをインストールします。
    パッケージ形式はバイナリで構いません。


  3. 以上で準備完了です。

GNUPLOTの使用方法

GNUPLOTはX Window System内で使用します。

X Window Systemの起動方法

GNUPLOTを起動するにはX Window System(xterm)内でコマンド"gnuplot"を実行します。

GNUPLOTの基本的な命令

詳細はマニュアル参照。

Appendix B. デバッガの使用法

バグとは想定した動作と実装したプログラムの動作の齟齬です。
従って、プログラムの動作を追うことによりバグの原因を特定することができます。

プログラムの動作を追う場合、古典的にはプログラムの適当な場所にprintf()を埋め込み、そこまで到着したというメッセージを表示するなり関心のある変数の値を表示するなりすることで、動作を追うことができます。(ログを取るといいます)
しかし、この方法ではログから動作を推測することになるため、ログに必要な情報が書かれていないときには役に立ちません。

必要な情報が変わるたびにログに書き出す情報を書き直しコンパイルするのでは非効率ですし、
かといって何でもかんでもログに書き込むとこれはこれで必要な情報を見つけにくくなり、やはり非効率です。

そこで、関心のある箇所の、関心のある情報をその時々の状況に応じて取り出すことのできるアプリケーションがあると便利に思われます。
それがデバッガです。(名前からすると自動でバグ取りをしてくれそうですが、もちろん取るのは人間です。)

このAppendixではX Window System上で動作するDDDというデバッガを例に、知っておくと便利なデバッガの使い方について解説します。
今回はDDDを取り上げますが他のデバッガ(例えばXcodeのデバッガ)でも大抵同様の機能があります。

DDDのインストール

DDDを動かすためにはX Window Systemが必要となります。
X Window Systemをインストールしていない人はAppendix Aの解説を参考にインストールしてください。
DDD自体は開発環境を構築するでインストールしたdevelパッケージに含まれているので、開発環境を構築するに従った人は既に使える状況になっています。

DDDの使用法

デバッガには主に次のような機能が備わっています。

これらの機能について、実際に使用しながら順を追って説明しましょう。

その前に、DDD(正確にはgdb)を使用するには、プログラムをデバッグできるようにコンパイルする必要があります。
デバッグする場合は、コンパイル時に -g オプションを付けてください。デバッグシンボル付きの実行ファイルを生成します。
試しに練習プログラム1をダウンロードし、次のコマンドでコンパイルしてください。

gcc -g -o debugger_exercise1 debugger_exercise1.c

では、この練習プログラム1を例にDDDを使用してみましょう。
まずDDDを起動します。
DDDを起動するには、Cygwinのコンソールでコマンド"startxwin.sh"を実行しxtermウィンドウが開くまで待ち、現れたxtermでコマンド"ddd"を実行します。

DDDのウィンドウが現れたら"File"メニューの"Open Program"項目を選択し、デバッグするプログラムを開きます。
試しに先ほどコンパイルしたdebugger_exercise1.exeを開いてください。次のようなソースコードが現れるはずです。
(行番号を表示するには"Source"メニューの"Display Line Numbers"項目を選択します。)



  1. では、10行目で実行を一時停止するようにブレークポイントを設定してみましょう。
    ブレークポイントを設定したい場所をクリックし、ツールバーにあるBreakボタンを押してください。
    (設定したい場所をダブルクリックでも可能です。)
    正しく設定できた場合は、ブレークポイントを表すSTOPと書かれたアイコンが現れます。
    ブレークポイントを削除するにはこのアイコンをクリックし、ツールバーのClearボタンを押します。
  2. プログラムを実行しブレークポイントで実行を止めてみましょう。
    サブウィンドウの"Run"ボタンを押すか、"Program"メニューの"Run"項目を選びます。(ダイアログでmain関数の引数を指定することもできます。)
    下図のように実行が一時停止した停止した場所に緑の矢印が現れるはずです。



    これだけでは芸がないので、この場所での局所変数等の値を表示してみましょう。
    まず、"View"メニューの"Data Window"項目を選択しData Windowを表示します。
    次に、"Data"メニューの"Display Local Variables"を選び局所変数の値を表示します。
    "Data"メニューの"Display Arguments"項目を選ぶと引数を表示することもできます。
    (下図中でiは初期化されていないため不確定な値を取っています。)



  3. ステップ実行してみましょう。
    ステップ実行には2種類あります。
    Step("Program"メニューの"Step"項目、またはサブウィンドウのStepボタン)とNext("Program"メニューの"Next"項目、またはサブウィンドウのNextボタン)です。
    Stepは関数の中に入っていきますが、Nextは入っていきません。
    試しにStepやNextを何度か実行してみて、動作の違いを確かめてください。
  4. 次のブレークポイントに行き着くまで実行を続けるには"Program"メニューの"Continue"項目(またはサブウィンドウのContボタン)を選びます。
    今回は次のブレークポイントがないのでブログラムが終了します。
  5. プログラムは関数呼び出しの組み合わせで作られています。
    そこで、どのような関数呼び出しの経路を辿ってブレークポイントまで行き着いたのか知ることができると便利です。
    スタックを見ることで関数呼び出し経路を知ることができます。

    練習プログラム1と同様に練習プログラム2をダウンロードし、次のコマンドでコンパイルし、DDDで開いてください。

    gcc -g -o debugger_exercise2 debugger_exercise2.c

    19行目(/* do nothing */と書かれた行)にブレークポイントを設定し、実行してください。
    停止した場所の関数呼び出し経路を知る(スタックトレースする)には"Status"メニューの"Backtrace"項目を選びます。
    下図のようなウィンドウが開きます。

    これは現在20行目の関数c()におり、
    この関数c()は13行目の関数b()から呼び出されたもので、
    更にこの関数b()は7行目の関数a()から呼び出されたもので、
    更に更にこの関数a()は24行目の関数main()から呼び出されたものであることを表しています。



    常にData Windowにスタックトレースを表示しておきたい場合は、"Data"メニューの"Status Displays"項目を選択します。
    現れたGDB Status Displaysダイアログ中の"Backtrace of the stack"チェックボックスにチェックを入れダイアログを閉じます。
    そうすると下図のように表示されるようになります。



以上でデバッガの基本的な使用法の解説は終わりです。

この他にも便利な機能があります。詳しくはDDDのマニュアルを参照してください。
例えば関数呼び出しにブレークポイントを設定することもできます。
練習プログラム1で、(gdb)と書かれた下のコンソールでコマンド"b add"を実行してみてください。
関数add()の呼び出しにブレークポイントが設定されます。
これを応用してプログラムの異常終了時に呼び出されることの多い関数exit()にブレークポイント設定しておけば、異常終了箇所を特定する手がかりになるでしょう。

デバッガとは直接関係ありませんがコンパイル時に -Wall オプションを付けると、プログラム中のバグに繋がる可能性のある箇所を警告してくれます。
デバッガを効果的に使用するためにも、読みやすいプログラムを心がけるのが第一です。

7. 更新履歴
文責: 園部勲