計算機言語 I 第 1 回 初めての C
1 これまでの講義資料とこれからの資料の記述について
以下 , Windows Subsystem for Linux を WSL と略記します .
最初の資料で , WSL で用いるエディタとして , TeraPad を推薦していましたが , 古いエディタなので , 標準の文字コードが SJIS (Shift-JIS) のようです . 前回の資料で述べましたが , サクラエディタは , 標準が UTF-8 なので , こちらの方がお勧めです .
Mac, WSL, Linux は , どの環境でも , 保存するファイルの文字コードは , UTF-8 に設定して下さい .
Visual Studio の利用者は , 文字コードは , Visual Studio のエディタのデフォルトを利用して下さい . Windows の文字コード は , かなり面倒な設定になっているようで (UTF-16 か日本語だと SJIS?), 私には手に負えません .
今年は , 受講生の環境が沢山あります . それら全てについて詳しく解説する能力はありません . 特に , Windows の Visual
Studio に関しては , 利用した経験がないので , 細かい解説はできません . あらかじめ了承をお願いします .
現時点で , C の処理系の導入が済んでいない方は , 早い時期にその理由をメールして下さい .
これからは , 教科書に従って講義を進めます . この資料は , 教科書の補足説明を書いていきます .
2 C を始める前に
処理系とエディタの導入はすでに済んでいると想定します .
2.1 ディレクトリの作成
講義では , 多くのファイルを作成します . ファイルを整理するために , 適当なディレクトリ ( フォルダ ) を作成して , そこで作業 します .
ディレクトリ ( フォルダ ) 階層を表す文字は , Mac, WSL, Linux では , / ( スラッシュ ) ですが , Windows では¥ ( 円記号 , 本来は
\ ( バックスラッシュ ) だが , 日本語環境だけこう表示される ) です .
コマンドラインからコンパイラを動かすには , Mac だと「アプリケーション / ユーティリティ」フォルダの中にある , ターミナ ル .app を使う必要があり , Visual Studio だとツールメニューから , 「コマンドライン → 開発者用 Power Shell 」を起動します .
コンパイルコマンドは , Mac, WSL, Linux では cc または gcc ですが , Visual Studio 環境では , cl ( シーエル ) です . Mac の
Xcode 環境だと Product メニューの Build というのもありますが , これについては , 資料に記述しません ( 使うのを禁止してい
るのではなく , それを使う人は , この資料をそれに合わせて読んで下さいという意味です .).
この講義では , Mac + ターミナル .app, Linux, WSL を中心に記述していきます . これらは , Unix という OS を起源にしてお り , C も Unix の開発用に作られたもので , 解説が簡単であるというのが理由です . Windows は , これらから見ると作られ方が違 うので , C の処理も違ったものになります . また , 入出力に対応するシステム構成も大きく違うので , 解説が大変です .
Mac や WSL では , C コンパイラからのメッセージが英語になると思います . そのような英語を読む癖をつけて下さい . コンパ
イラからのメッセージは , 技術用語 (Technical Term) がわかれば , 英語としては難しいものではありません . 現実に起こっている
のは , 往往にして , 英語がわからないのではなく , 技術用語がわからないというところです .
3 教科書の補足
教科書の 1.1 – 1.10 節はよく読んで下さい . ただし , 1.3 節のフローチャート (flow chart) はこの講義では , 使いません .
3.1 教科書 1.11 節
この節にある C のプログラム sample.c をコンパイルし , 実行してみてください .
• Mac, WSL, Linux では , ほぼ教科書通りです .
1. まずは , sample.c の内容を持つファイルを適切なエディタで作成し , 適切なフォルダに保存します .
2. 端末エミュレータを利用します . ファイル , sample.c があるフォルダにワーキングディレクトリを移動して , 教科書通 り (p. 14 先頭 ) のコマンドで実行できます .
• Visual Studio では , 標準のエディタで sample.c の内容を記述し , このファイル名で保存し , コンパイルして実行します . より具体的には , 次のようにします .
1. このファイルの内容を入力するには , 「ファイルメニュー → 新規作成 → ファイル」を選択し , 左の欄にある「 Visual C++ 」を選んで , 右の欄の「 C++ ファイル」を選びます . そうするとエディタ画面になるので , 入力をしていきます . 括弧の補間とかを自動的にしてくれます ( 私的には , 大きなお世話レベルになってる ).
2. 保存するには , 「ファイルメニュー → 名前をつけてソース 1.cpp を保存」を選びます . 保存ファイル名を決めるウィン ドウが出てきますが , ファイル名を「 sample 」とし , その下の欄のファイルの種類を , 「 C ソースファイル (*.c) 」を選べ ば , sample.c というファイル名で保存されます .
3. 上で作った sample.c. をコンパイルするには , メニューで「ツール → コマンドライン → 開発者用 PowerShell 」を選 びます ( 開発者コマンドプロンプトでも良い ).
4. コンパイルのためのコマンドは , cl sample.c です .
5. 作成される実行可能ファイルは , sample.exe というファイル名になります .
6. これを実行するには , PowerShell ( あるいはコマンドプロンプト ) で , ./sample とタイプして Enter を押します .
gcc や cl のコンパイルがうまく実行できなかった人は , エラーメッセージを読んで , 次をチェックしてください . 1. ワーキングディレクトリは , 正しいか ? (Mac, WSL, Linux の場合 )
2. 文字コードが utf8 で保存されているか ? (Mac, WSL, Linux の場合 ) 3. ファイル名は , sample.c となっているか .
4. コマンド又はファイル名を正しくタイプしたか ?
5. ソースコードの括弧や 2 重引用符 (") は , 正しく入力されているか ? ( 全角文字になっていないか ?) 6. #include の # は行の先頭にあるか ?
7. printf 文の最後にセミコロン ; がついているか ?
この節に対する補足
1.11 節の先頭に GCC は Windows でも動作するとあります . 実際 , MinGW(Minimalist GNU for Windows) というパッケー ジがあり , その中に GCC (GNU Compiler Collection) もあります .
それを導入してコンパイルすると何が起こるかというと , Windows Defender. が , 実行可能ファイルができた途端にそれを削 除します . Windows Defender 的には , MinGW. で作成したファイルは , セキュリティ上の脅威と判断するようです .
Windows Defender を設定すれば , 使えるようになるのですが , その解説をするのも大変なので , この講義では , MinGW を使
わないことにしました .
sample.c のプログラムの説明
上で動かしたプログラムの意味を順番に見て行きます .
#include <stdio.h>
# で始まるこの部分は , C プリプロセッサ (preprocessor) cpp への命令です . ( 後の講義で追い追い解説しますが , とりあえずはお まじないと思って下さい .)
int main(void)
main と言う関数の始まりを示します . C 言語でコマンドプロンプトから実行可能なプログラムを作る時は , 必ず main と言う名
前の関数が必要で , ここからプログラムの処理がはじまるようになっています . 行頭の int は , main 関数の返り値をしてしてお
り , int は「整数型」 ( 後の講義で解説する ) という意味です . () の中には , この関数のパラメータ ( 通常プログラミングとか計算
機の分野では , 引数という .) が入ります . void という言葉は , C 言語のプログラムで様々な現われ方をしますが , 関数引数で用い
られるときは , 引数無しの意味になります . 従って , この void は省略できます .
{
printf("Welcome to C world! \n");
return (0);
}
ここが , プログラムの本体です . C 言語では , 一連の処理は中括弧 { と } で挟んで書きます . 中央の printf("Welcome to C world! \n");
が , このプログラムがする全てです . printf は , 標準入出力ライブラリにある関数です . 2 重引用符 ” で囲まれた文字列を標準出 力に表示します . printf は計算機概論 I の awk のプログラムでも出てきましたが , それと同じ動作をします . 教科書には , その 使い方が順次説明されるはずなので , その時には , 教科書を読むようにしてください . プログラミング言語では , コンピュータへ の 1 つの命令を「文」 ( これはきちんとした専門用語 ) と言います . C 言語では , 文の終わりをセミコロン ; で表すのが決まりと なっています .
最後の return (0); は , この main 関数が 0 という値を返すという意味で , どこに返すかというと , これを起動したプログラ ム , Mac, WSL, Linux の場合は bash (shell の 1 つ , コマンドプロンプトを見よ .) です . bash はこの値を status という名前の (shell) 変数に保持しています . 次で , それは確かめられます .
echo $status
Visual Studio の場合は , どうなっているのか知りませんが , おそらく OS はその値を捨てていると思われます .
3.2 教科書 1.12 節 : 数学関数ライブラリを使う
上の printf のように , プログラムでよく利用される関数は , ライブラリという形で予め作られており , それを利用することで ,
プログラミングの量を減らします . ただし , ライブラリ関数は多量にあり , 実際に必要となるものは少数です .
そこで , C では , ライブラリ関数をいくつかに分割して保存しています . 何も指定せずに利用できるライブラリ関数をまとめた ものが , 「標準ライブラリ」です . 3 角関数や指数関数など , 数理の皆さんにはおなじみの関数の , 世の中ではあまり使われないよ うです . このような関数をまとめたのが , 「数学関数ライブラリ」です . Mac, WSL, Linux でこれを利用する方法が , p. 16 に書 いてあります . Visual Studio では , オプション無しで数学関数ライブラリが利用できます .
教科書 p.16 の内容 (sample2.c のコンパイルと実行 ) を実行してください (Visual Studio でのコンパイルでは , コンパイラに対するオプションは不要 ).
Unix 系の環境で数学関数ライブラリを利用するのに , コンパイラにオプションが必要なのは , C. が OS. を作るための言語とし て開発されたという歴史的な事が理由です . OS は , コンピュータを効率よく利用できるという事を目標に作られます . 実行可能 ファイル (OS に付随するコマンド ) も , できる限り無駄のない造りを要求されます . 数学関数などは , 特別な場合にしか必要とさ れませんので , 必要な場合にのみ利用する形にしたのです .
Visual Studio は上のような考え方をしなかったようです . Windows も C を用いて書かれている可能性もありますが ,
Microsoft がどのような意図で , Visual Studio. というソフトウェアを作っているかは , わかりません .
gcc の実行時のオプション -lm は , 次項以下に書かれているリンクエディタ ( リンカ ) ld がその意味を解釈して実行してい
ます .
3.3 教科書第 1 章全般に対する補足
計算機概論で述べたように , コンピュータは 2 進法の数しか扱えません . それに対して , 人間は , 数は多くの場合 10 進法で記述 しますし , いわゆる自然言語を利用して物事を進めます . この人間とコンピュータの間を取り持つのが , プログラミング言語です . 人間に近い言葉で , コンピュータに指示を与えるためのものです .
C の処理系は , C の文法に従って書かれたコンピュータへの命令を , コンピュータが実行可能な機械語に変換するためのソフト ウェアです . 実行可能ファイルな機械語ファイルを作るので , コンパイラと呼ばれる種類の処理系です ( 計算機概論を復習せよ ).
教科書で用いている gcc とは GCC(GNU Compiler Collection) の中の C コンパイラで , 多くの OS に移植されている無料の コンパイラ処理系です . 皆さんが利用していた CentOS では , cc と呼ばれる C 言語処理系としては標準的なコマンドもあります . CentOS では , cc の実体は gcc で , コマンド名の違いは , コンパイラオプションで gcc の方が通常の (ANSI で定義されている ) C コンパイラより拡張した機能が利用できるか否かだと思われます . 拡張されたコンパイラ機能を使うことは , 移植性の低下の可能 性があるので , 通常は , cc コマンドで処理するようプログラムを書きますし , この講義では , 拡張された機能を使うことはありま せん .
Visual Studio の C コンパイラは , C 言語処理系の Windows. に対する Microsoft の実装です .
以下で述べている内容は , Unix 以来の伝統的な C コンパイラの動作です . C の仕様として , 以下のように動作する必要はない ので , Visual Studio では , 途中のアセンブラ部分は省略しているようです .
コマンド gcc は 1 つのプログラムではなく , 少なくとも次のプログラム ( プロセス ) を利用します . 下の図の四角く囲まれた部 分に書かれているのは , その時に使うファイル名です . Column 1-1 で , プログラムの実行まで 8 段階の処理とありますが , 何を 1 段階と数えるかという悩ましい問題もあります . とりあえず a.out の作成までの段階で , 目で確かめられる内容として , 次の 4 つ に分けて見て行きます .
*.c −→ cpp *.c −→ ccom *.s −→ as *.o −→ ld a.out
cpp C preprosessor: C compiler (ccom) が処理をする前に , コメント文の削除や , マクロの展開などの文字列処理の部分を受け 持って , 事前に処理をするものだと思ってください .
ccom C compiler: C 言語の文法で記述された処理内容を , assembly 言語に変換するプログラム .
as Assembler: assembly 言語で書かれた内容を , 機械語 (2 進法で記述されもの ) に変換するプログラム .
ld Link editor: リンカともいう . 上の sample.c ではコンパイルした結果は , 文字列 Welcome to C world を出力ライブラリに 渡すという内容になります . printf のような関数はライブラリとしてコンピュータの次にファイルに入っています .
/usr/lib/libc.a (/usr/lib/libc.so.1)
ld は , sample.c のコンパイルしてできた結果と上のファイルにある printf を結び付けて ( リンクするという ), さらにシステ
ムが実行時に要求する情報をつけて , 実行可能ファイルを作り上げます .
Library プログラムを組むと分かりますが , 画面の入出力などはどのプログラムでも同じ様な事をします . これをいちいちプログ
ラムするのは , 無駄です . そこで , よく使う処理はあらかじめ機械語のものを作成し , まとめたのが必ずあります . これがラ イブラリ (library) です . ライブラリは , compiler( 実は , リンカ ) に指示することによって , 自分のプログラムにくっつける ことが出来ます . また , C 言語では標準ライブラリというのが ANSI(American National Standard for Industory, アメリカ 工業規格 ) により定義されており , 多くの処理はこれを利用します .
ファイル名 C 言語のプログラミングにおいてファイル名は , 次の規則にしたがって , 名前をつけます .
1. *.c C 言語のプログラムを記述したファイル .
2. *.h ヘッダ (header) ファイル . 定数とか関数の定義を記述する .
3. *.s assembly 言語のプログラムを記述したファイル . (Visual Studio では無い .)
4. *.o オブジェクト (object) ファイル . 2 進法で記述した機械語が入っている . (Visual Studio では , *.obj)
5. a.out 特別なオプションを指定せずにコンパイルしたときに出来る実行可能ファイル (Mac, WSL, Linux の場合 ).
上のファイルのうちいくつかは , sample.c をコンパイルするときには現われませんでしたが , それは単に目に見えないだけ
で , コンピュータの内部ではちゃんと作られています .
実際に処理を途中で止めた結果を見ます . cpp 段階で止めるには , E のオプションで cc を実行します . その結果は標準出力に出 力され長いので , more にパイプします . Unix 系 (Mac, WSL, Linux) ではオプションを示す記号は - ( ハイフン ) ですが , Visual Studio (Windows のコマンド ) では , オプションは / ( スラッシュ ) に続く文字列です .
gcc -E sample.c | more (Mac, WSL, Linux) cl /E sample.c | more (Visual Studio)
最初の部分は , コメントの削除と #include <stdio.h> の結果で , ( どこかにある ) stdio.h というファイルを取り込んでいます . 実 際に書いたプログラムの本体は , 一番最後の部分に現れます . そこでは , コメント文が取り除かれています .
assembly 言語の場所で処理を終わらせるには , オプション -S を用います . Visual Studio はこれが出来ません . gcc -S sample.c
今度は , 結果は画面ではなく , ファイル sample.s に保存されています . cat sample.s
ファイルにある movl とか movq とかは , アセンブリ言語で , cpu に対する 1 つの命令を表します (mnemonic ( ニーモニック ) と いう ). さらに 1 つ先のオブジェクトコードの状態までで止めるには , c( 小文字 ) オプションを用います . これは , どの環境でも可 能です .
gcc -c sample.c (Mac, WSL, Linux) cl /c sample.c (Visual Studio)
やはり出力は画面ではなく , sample.o (Visual Studio では , sample.obj) というファイルです . このファイルは機械語からなって
いるため , かなり特殊な能力がないと人間には理解できません .
さらに補足
• WSL で作った実行可能ファイルは , Windows のコマンドプロンプトでは実行できません . 逆に Visual Studio で作った実 行可能ファイルは , 拡張子まで込めてファイル名をタイプすれば , WSL 環境で実行することができます .
• Visual Studio を使っているとよく出てくる C++ は , C を拡張してオブジェクト指向プログラミングができるようにした言
語です . C のオブジェクト指向拡張には , Objective C というのもあります .
レポート問題