プログラムを起動するときに、そのプログラムの起動時に引数を与える とそれに対して処理を行なってくれる。たとえば、cat コマンドは
cat score.txt
のように、「cat ファイル名」と打てばそのファイルの中味を表 示してくれるし、
cat -n score.txt
のように -n
をつければ、指定したファイルを行番号つきで
表示してくれる。また、gcc コマンドは
gcc -o hoge hoge.c
のように起動すると「hoge.c をコンパイルして hoge という実行ファイルに
せよ」という意味で解釈してくれる。このように、どんなプログラムでも通常は
プログラムを起動するときに「何を」、「どう」処理す
るのかの指定を行なえるようになっている。「どう」処理するのか
はたいていの場合 -
(ハイフン) で始まる引数で指示する。
このような引数のことを特別にオプション という。catの
場合は -n
オプションが、「行番号をつけながら」という
追加機能を指定し、gccの場合は -o
オプションが、
「出力するファイル名を次の引数で指定するものにせよ」と指定する
ようになっている。
自分が作るCプログラムでも、このように(オプションを含めた)引数を 解釈するようにしておいた方が便利である。
C言語では、プログラム起動時には最初にmain
関数に
処理が渡る。このときに、main
関数にコマンドライン引数に
与えた(複数の)文字列(へのポインタ)が配列として与えられるようになっている。
これまで main
関数は、
int main()
{ .... }
のようになにも引数を取らないように記述していたが、実際にはコマンドラ イン引数の配列を渡されている。渡されるのは、
int main(int argc, char *argv[])
{ ... }
のように、第1引数は整数、第2引数は文字列へのポインタの配列である。
この説明では分かりづらいので実例を見よう。自分で作ったプログラム
foo
を、次のように起動したとする。
./foo -o hoge hoge.c
すると、システムはこのコマンドラインを次のような引数構成だと 考える。
第0引数 | 第1引数 | 第2引数 | 第3引数 |
./foo | -o | hoge | hoge.c |
そして、この4つの文字列(が格納されているアドレス)を配列にして
main
関数に渡す。すると、main
関数がもらう引数
argc, argv
は以下のように文字列と結びつけられる。
argc | 4 (int) |
argv[0] | "./foo" (の格納アドレス) |
argv[1] | "-o" (の格納アドレス) |
argv[2] | "hoge" (の格納アドレス) |
argv[3] | "hoge.c" (の格納アドレス) |
argv[4] | NULL |
どのようにプログラムを起動しても(引数なしでも)、必ず
argv[0]
は起動したプログラム自身を指すことに注意する。
また、必ず配列の最後の値は NULL となる。
とても簡単な例として、cat コマンドと同じように引数として与えられた
ものをファイル名と見なし、そのファイルを表示するプログラム
dog.c
を作ってみよう。
./dog score.txt
のように起動する場合、argv[1]
に "score.txt"
が渡されるので、これを fopen
するようにプログラムを書けば良い。
#include <stdio.h>
int main(int argc, char *argv[])
{
FILE *fp;
char buf[10];
if (NULL == argv[1]) {
fp = stdin;
} else {
fp = fopen(argv[1], "r");
if (NULL == fp) {
fprintf(stderr, "%s というファイルは読めないの..\n", argv[1]);
exit(1);
}
}
while (NULL != fgets(buf, sizeof buf, fp))
printf("%s", buf);
if (stdin != fp)
fclose(fp);
}
実際には、main
関数にはもう一つ引数が渡される。
これは慣習的に envp
という変数で受け取る文字列への
ポインタの配列である。
int main(int argc, char *argv[], char *envp[])
{ ... }
この配列に入っている文字列は環境変数といい、システムが
持っている変数の値である。コマンドラインで env
コマンドを
実行すると環境変数の一覧が得られる。
env
USER=c101345
LOGNAME=c101345
HOME=/home/irhome/c101/c101345
:
:
:
この例では、変数 USER
の値が c101345
で、
変数 HOME
の値が /home/irhome/c101/c101345
となっている。このような状態で、C言語で作成したプログラムを起動すると
第3引数 envp
は以下のようになる。
envp[0]
USER=c101345
envp[1]
LOGNAME=c101345
envp[2]
HOME=/home/irhome/c101/c101345
:
::
:
環境変数を使ってプログラムに指令を与えることができる。ただし、
任意の環境変数の値はライブラリ関数 getenv
を使って手軽に
得ることができるので、main
関数の第3引数envp
を使う機会はまれだろう。次のプログラムは環境変数 USER
の値(つまりユーザ名)に応じてメッセージを出力するものである。
#include <stdio.h>
#include <stdlib.h> /* getenv() で必要 */
int main(int argc, char *argv[]) /* envp は使わない */
{
char *user = getenv("USER");
if (user) {
printf("%s さん こんにちは\n", user);
} else {
printf("%s さん こんにちは\n", "名無しの権兵衛");
}
}