K&R C言語 入門その1

こんにちは、童爺です。
今回からは、Linux(Unix)プログラミングをテーマに記事を書いていこうと思います。
開発環境は、CentOS7です。
ホームディレクトリ配下に、workディレクトリを作ってその中で色々説明して行こうと思います。

最初は、K&RのC言語を中心にやっていきたいと思います。
といっても、ただ解説や補足するだけでは面白くないので、アレンジしたいと思います。
教材は以下のプログラミング言語C 第2版 ANSI規格準拠。
俗に言う、K&R本です。

記念すべき第一回目は、hello, worldです。

Hello, Worldについて

本書では以下の文体になっていると思います。

#include <stdio.h>

main()
{
	printf(“hello, world\n”);
}

それでは、1行ずつ解説しましょう。
まず、

#include <stdio.h>

ですが、これは標準入出力ライブラリを取り込むと書かれています。
正確には、Standard Input Outputの略で、下線部の文字を取り出しstdio.hとしています。
何故、こんな事をしているかというと、昔のPCはファイル名が8文字以内で拡張子が3文字以内までしか表現できませんでした。
ですので、省略してあります。

今はロングネーム(長い文字名)が使えるので、長い名前を使って解りやすくするのが一般的になっています。
(まあ、それでも短く省略するのが伝統みたいな所もあるので、ケースバイケースですね。)

次に関数のmain()ですが、省略しすぎです。
上記のようなプログラムを組むのであれば、以下の様なのが一般的です。

void main(int argc, char *argv[])

です。
voidは、値を返さないと言う意味。
int argcはプログラム実行時のオプション数。
char *argv[]はプログラム実行時のオプションが文字列で入ってきます。
char **argvと書く人もいます。
これも正解ですが、後々説明するポインタと文字列で、どう違うのか説明したいと思います。

さらに余談ですが、Linux(Unix)で、伝統的なmainの書き方は以下の通りです。

int main(int argc, char *argv[], char *envp[])

です。

既にC言語をマスターしている方は、「おやっ?」と思った人もいるのではないでしょうか?

char *envp[]

が多いですね。
これは、プログラム実行時の環境変数が格納されてきます。
ですが、省略されるのが一般的です。
何故か?
それは、envpを引数でもらわなくても、getenv関数で取得できるからです。
では、何故あるのかと言いますと、getenv関数はglibcというライブラリに含まれているのですが大きすぎて、Linux(Unix)起動時にglibcが読み込まれるまで若干時間がかかります。
なので、glibcが読み込まれるまでの間、例えばカーネルに近い部分のプログラムではenvpで環境変数を取得する必要があります。

脱線しましたね。

では次の

printf(“hello, world\n”);

です。
これは本書に書いてある通りです。
補足として、無条件にstdout(標準出力)に、出力されます。

Linux(Unix)には、三つの標準入出力があります。
stdoutは標準出力。
stderrは標準エラー出力。
stdinは標準入力です。

何故こんなものがあるのでしょう?
それは実践的なプログラムでは、何でもかんでもプログラムから標準出力に出力すると、ただのログなのかエラーで出力したログなのか、見分けが付かないからです。
ですので、fprintf関数を使います。
実際にfprintf関数を使ったプログラムを書いてみましょう。

#inlucde <stdio.h>
int main(int argc, char *argv[])
{
	fprintf(stdout,”hello, world\n”);
	return 0;
}

このプログラムを、以下の様にコンパイルして実行してみましょう。

$ gcc main.c
$ ./a.out
hello, world
$

となります。

では、今度はstderrを使ってみましょう。

#include <stdio.h>

int main(int argc, char *argv[])
{
	fprintf(stdout, “これは正常です!\n”);
	fprintf(stderr, “これはエラーです!\n”);
	return 0;
}

これを先ほどと同じくコンパイルして実行してみましょう。
ファイル名は解り易く、main_stdio.cとします。

$ gcc main_stdio.c
$ ./a.out
これは正常です!
これはエラーです!
$ 

となります。
これだけでは、メリットは無いように感じますが、以下の様に実行してみて下さい。

$ ./a.out 1> ok.log 2> ng.log
$

これで、ok.logとng.logの内容を見てみましょう。
ok.logの中身。

これは正常です!

ng.logの中身

これはエラーです!

となります。
このように、普通の文言とエラー時の文言を分ける事ができます。

まとめ

どうでしょうか?
ただのhello, worldプログラムでも色々奥深いものがあると思います。
たかがhello, worldされど、hello, worldは基本中の基本です。
しっかり理解して次に進みましょう。


それではまた。
でわでわ。

シェアする

  • このエントリーをはてなブックマークに追加

フォローする

童爺 童爺のプロフィール
童爺は「どうじ」と読んでください。 由来は友人に、ハンドルネームを「酒呑童子」にしようかと相談したら、「酒呑童爺」にしたらどうかと言われたのが由来です。(爺むさい所や、子供っぽいところがあるからです。)