mainの引数 argv の構造

システム・プログラム

                                       電子・情報工学系
                                       新城 靖
                                       <yas@is.tsukuba.ac.jp>

このページは、次の URL にあります。
http://www.coins.tsukuba.ac.jp/~yas/coins/syspro-2004/2004-04-19 /argv.html
あるいは、次のページから手繰っていくこともできます。
http://www.coins.tsukuba.ac.jp/~yas/
http://www.is.tsukuba.ac.jp/~yas/index-j.html

■mainの引数 argv の構造

◆コマンドラインとexecve()

プログラムを実行する時、シェルから引数を渡すことができる。 あるいは、execve() システムコールで引数を渡すことができる。
   1:	/*
   2:	        arg-print.c -- mainの引数を表示するプログラム
   3:	        ~yas/syspro/proc/arg-print.c
   4:	        Start: 1997/04/21 18:23:13
   5:	*/
   6:	
   7:	main( int argc, char *argv[], char *envp[] )
   8:	{
   9:	    int i ;
  10:	        printf("&argc == 0x%x, argc == %d\n", &argc, argc );
  11:	        printf("&argv == 0x%x, argv == 0x%x\n",&argv, argv );
  12:	        for( i=0 ; argv[i] ; i++ )
  13:	            printf("argv[%d]==0x%x, \"%s\"\n",i,argv[i],argv[i] );
  14:	}
実行例。

% cp ~yas/syspro/proc/arg-print.c . [←]
% make arg-print [←]
cc     arg-print.c   -o arg-print
% ./arg-print  [←]
&argc == 0xbfffe7c0, argc == 1
&argv == 0xbfffe7c4, argv == 0xbfffe824
argv[0]==0xbffffa81, "./arg-print"
% ./arg-print who am i [←]
&argc == 0xbfffe740, argc == 4
&argv == 0xbfffe744, argv == 0xbfffe7a4
argv[0]==0xbffffa78, "./arg-print"
argv[1]==0xbffffa84, "who"
argv[2]==0xbffffa88, "am"
argv[3]==0xbffffa8b, "i"
% []
argv[0] には、プログラムの名前が含まれている。argv[1] 以降に、普通の意 味での引数が含まれている。argc には、プログラムの名前まで含めての引数 の数が含まれている。argv[0] からargv[argc-1] まで参照できる。 argv[argc] は、参照してはいけない(0が入っているはずではあるが)。

argvは、2次元配列ではない。 char へのポインタの配列の先頭番地を入れた変数である。

argvの構造、3つのメモリ

図? argvの構造

◆C言語のポインタと配列、2次元配列

C言語で char *argv[] は、*argv[0] と書いたら char 型(8ビットの 整数)という意味である。

C言語で char *p と宣言した時、*pp[0] は、 同じ意味になる。 *(p+1)p[1] も同じ意味になる。

2次元配列は、C言語では配列の配列として表される。

	char array[10][20];
これで、全部で 10*20*1 == 200 バイトのメモリが確保される。array[i][j] の番地を計算するには、次のようになる。

	(1) arrayの先頭番地を求める。
	(2) (1)の値に + i*20 を加える。
	(3) (2)の値に j を加える。
array[10][20] のうち、最初の [10] は、番地の計算には使われない。

main() の引数で char *argv[] と char **argv は、同じ意味になる。 argv[i] は、 *(argv+i)、 argv[i][j] は、*(*(argv+i)+j) という意味になる。

char *argv[] で、argv[i][j] と書いた時の番地の計算の仕方は、次のように なる。

	(1) argv の番地の内容を load する。
	(2) (1)の値に + i*4 を加え、その値の番地の内容を load する。
	(3) (2)の値に j を加える。
2次元配列と違って、番地を求めるだけで、間に load が2回入る所に注意す る。2次元配列だと番地を計算する時には、load は出てこない。

(main の)引数で、char *argv[] と char **argv は、よいが、char argv[][] は、伝統的にはエラーになる。argv[i][j] を計算しようとすると、i を何倍 してよいのか計算できないので。しかし、受け付けるコンパイラもある。

C 言語で、char a[10] とした時には、10 バイトの領域が確保される。しかし、 char *p 宣言しただけでは、ポインタ自身(4バイト)の領域は確保されるが、 その先の領域は確保されない。

ポインタは、必ず番地をセットしてから使う。次のプログラムは、誤りである。

main()
{
    char *p ;
	*p = 'A' ;
}


Last updated: 2004/04/18 22:28:42
Yasushi Shinjo / <yas@is.tsukuba.ac.jp>