C言語の初めの一歩

Hello, world!!

さて、いい加減に前置きは疲れた。本題に入ろう。では、最初のC言語のプログラムということで。どこでもよく見かけるコードだ。

#include <stdio.h>

/* My first C language program!! */
int main(void)
{
	printf("Hello, world!!\n");

	return 0;
}

以上だ。さて、ここではとりあえず、細かい薀蓄を語る前にすることがある。

前にも書いたとおり、プログラミングはプログラムを実際にしない限り、絶対に覚えることはない。というわけであなたがこれをコンパイルして実行ファイルを作ることが出来るか、つまりプログラミングの環境が整っているかをこれで確認してみよう。以後、コンパイルのことについて述べることはほとんどないのでここできっちり実行ファイルを作れることを確認して欲しい。

Unix系OSを使っているかWindowsでMinGWを使っている場合

まず、ターミナルを開いて適当なディレクトリを作成、移動する。ホームディレクトリーで作業しないのは当然だな。例えばこんな感じ。

% mkdir c_lang
% cd c_lang

次にお気に入りのテキストエディタを開く。vi、vim、mule、emacsなどどれでも。WindowsのMinGWなら秀丸、メモ帳でもいい。ワードパッドやMicrosoft Office Wordとは気をつけないとテキスト形式じゃなくて独自のフォーマットで書き出されるので要注意。というか、そんなもの、プログラミングに使うな。

そしておもむろにソースを打つ。コピーアンドペーストでもいいけどなるべく打って実感してほしい。ファイル名はとりあえず、「first.c」あたりにしておこうか。実際にはファイル名は何でもいいけど拡張子は必ず".c"。

打つときの注意事項としては「全て半角」「printf、returnの前はスペースじゃなくてTab」。Vimとかだと自動的にTabが入った入りするかも。

打ったら保存、終了。viなら":wq"、muleなら"C-x C-c"。ただ、プログラマーは普通、5分毎にセーブする。というのは自分の書いたプログラムが完全じゃない以上、いつシステムが落ちるかわからないからだ。1時間ソースを書いたら保存してないのにシステムが死んだ、これじゃあ泣けてくるからな。

ターミナルに戻る。次のように打つ。これがコンパイル。

% gcc -c first.c

ここで何も文句言われなければ成功。文句言われたらタイプミスあり。ソースを見直す。

とりあえず、下のように打つ。

% ls

その結果

first.c first.o

のように「first.o」というファイルが出来ているはず。

実行ファイルを作るにはリンクという作業をする。とりあえず、次のように打つ。

% gcc first.o -o first

とりあえず、また確認。

% ls

とすると、Unix系OSの場合は多分、

first first.c first.o

MinGWでは

first.c first.exe first.o

となっているはず。そう、Unix系OSではfirst、MinGWではfirst.exeが実行可能ファイルとして出来た。

実はこのコンパイルとリンクはこのような小規模なプログラムでは分けてやるメリットはない。なので初めっから

% gcc first.c -o first

とやってもいい。こうすると突然、"first"という実行ファイルを作ってくれる。実はさらに"-o first"を省略することもできる。

% gcc first.c

これで充分。この場合、実行ファイルの名前はUnix系OSではa.out、MinGWではa.exeになる。

ありあえず、おもむろに実行してみる。

% ./first
Hello, world!!

と表示されれば成功、されなかったらどこか間違っている。探すべし。

GCC

コンパイラ、とは言っても世の中、たくさんある。今回はgccを使ったがこれ、いくつか有用なオプションがあるので紹介しておこう。これ以外にもそれはそれは大量にあるのでmanコマンドで調べてみたらいかが。

-O
-O2
-O3

最適化をする。ちなみに"O"は数字のゼロじゃなくてアルファベット大文字のオー。普通は-Oを使う。-O2、-O3はより最適化が進む。でもふつーは-O2や-O3は使わない。というのはコンパイル時間が劇的に増える割に効果が少なく、またコンパイラ自身の潜在的バグが-O2や-O3だと表面化したりするからである。よほどのことがない限り、-O2や-O3を使うメリットはない。というわけで-Oを使うべし。

-Wall

Warning、つまり警告を全て出す。

コンパイラが言ってくる「文句」には二種類ある。Error、つまりエラー、そしてWarning、つまり警告。

エラーは一言でいうと「意味不明」。「が私のれる名前がはてっちゃんではだ。」という感じである。つまり要はわからん。エラーの場合、解読不能なわけだからコンパイルは行われない。何行目にどういうエラーがあるか表示されるだけである。

警告は「意味はわかるんだけど本当なの?」という感じ。「沖縄では本日の積雪量が60cmを越えました。」とか「地球の公転周期は1日です。」みたいな。そしてこの場合、とりあえず、プログラマーの言うことを信じてコンパイルが行われる。

・・・が、警告は10中9以上の確率でプログラマーにとっても間違いである。沖縄でそんな大雪が降るはずがないし地球の公転周期は約1年である。というわけで警告もエラーと思って全てなくすべし。

-Wallはコンパイラが不思議に感じたことを全部、言ってくれる。そして、それは大抵、的を得ている。だから-Wallを使って常に警告が出ないようにしよう。これがプログラムの修正第一歩。

-g

gdbというデバッガを使う場合に有用なオプション。実行中にソースのどの部分に相当するところを実行しているかとか、変数の値を読み出したりできる。まあ、とりあえずはいらない。

というわけで

% gcc -O -Wall first.c

がお勧めか。

実際のプログラムではこれの繰り返しをやる。ソースを打ってコンパイル、ソースを打ってコンパイル・・・

Windows Visual Studio、Visual C++などの場合

工事中

プログラムの書き方

日本語にしてもそうだけど意味のわかる書き方、わからない書き方、わかるけど読みづらい書き方がある。

  1. うちのにわにわはにわにわとりがいます。
  2. う ちのにわに はにわに わと りがい ます。
  3. うちの にわには にわ にわとりが います。

ちなみに漢字を交えて書くと「うちの庭には二羽鶏がいます。」

全てひらがなで書いてみたわけだがどれが一番わかりやすいだろうか。全て全く同じ文章だけど僕は3がわかりやすい思う。あなたは?何、1、なら言うことありません。(爆)

ちなみに2は文節、単語の途中で区切られてしまっているので意味不明である。

実はC言語の書き方にも同様なことがいえる。つまり、変なところで切らない限り、どこにスペースをいれても改行をいれてもいいことになっている。

ということは、いわゆる読みやすいプログラムを書いた方が言い訳で例の1のような書き方はよくないことになる。2は意味不明、エラーとなるわけだ。

しかし読みやすいプログラムというのは人によって様々なので「これがいい」というスタイルはない。一応、Hello, world!!の例では一般的には読みやすいといわれる方法で書いたつもりだけど。

その辺をちょっと見てみることにする。

いきなりだが一行目にある#include のように#から始まっている行は一行にこれしか書けない。これ以降に続けて書くのは駄目(意味不明になる)。よってこの行にはこれしか書けない。ただ、includeとの間のスペースは任意である。

その後、一行あいているがこれは僕の勝手である。見やすいと思ったからである。不要ならいらない。・・・が、アドバイスとしては適度な空行はプログラムを非常に読みやすくするので入れた方がいい。

次に/* */で囲まれた部分があるがこれはコメントである。コメントとはつまり覚書である。覚書だからコンパイラが理解できる必要はない。なので日本語でも構わない。また、コンパイラからすればこの部分は無視なのでそもそもこの行自体いらない。・・・が、プログラムを組みだすとわかるのだが自分の書いたソースでさえ、一ヶ月もすれば全く覚えていないものなのだ。コメントを書いておかないと後々プログラムを見直すのが大変になることを指摘しておこう。

ちなみに複数行にわたるコメントも/* */で書けるけど装飾したい場合以外は使わない。その場合はこうする。

#if 0
コメントだよ
コメントだよ
コメントだよ
コメントだよ
#endif

つまり、#if 0と#endifで囲む。正確にはこれはコメントではないんだけど/* */の代わりによく使われる。

事のついで、装飾をしたコメントということで次のように書く人もいる。

/****************************************/
/*                                      */
/*     僕の始めてのプログラムだよ!      */
/*                                      */
/****************************************/

これも立派なコメントでしょ、/* */に囲まれているもの。目立たせたいときにどうぞ。

次のint main(void)だがint mainの間のスペースは必須。mainと(void)の間にスペースを入れてもよい。(void)は( void )とかでも構わない。

また、次の行の中括弧({)をこの行の後ろに付けてもよい。これはこうする人、結構いる。

";"は日本語でいう句点にあたる。つまり、区切りである。普通、C言語では複数の文を一行には書かないので;の後は改行してある。が、これも強制ではない。

printfとreturnの前のタブは不要ではあるが入れるのが半ば常識である。

printfと("Hello, world!!\n")の間にスペースを入れても構わない。ちなみにprintf()内は""の中は結果がそのまま表示されるのでHello, world!!\nとかすると実行結果が変わるので注意。

returnの後のスペースは必須。

そういうわけで見栄えを気にしなければ例えばこれでもいいことになる。

#include <stdio.h>
int main(void){printf("Hello, world!!\n");return 0;}

でも見にくいのでこういう書き方はやめような。

くわしすぎるC