Shammer's Philosophy

My private adversaria

要素数文字数不特定の文字列配列の扱い

hostent 構造体の内容も構造体の中身を埋める方法も、gethostbyaddr man page - Shammerismの内容でわかったので実際に挑戦してみたが、文字列の配列(char ** のデータ、つまり、h_aliases と h_addr_list)の要素数のカウントがうまくできず・・・解決方法を探していたところ、次のサイトを見つけた。

 http://forums.devshed.com/c-programming-42/hostent-structure-looping-h-addr-list-90333.html

Cで文字列の配列を扱う場合のやり方がよくわかる。
まず、文字列は、文字の配列。つまり、文字列の配列は、文字の配列の配列。ここで問題なのは、各文字列の長さが同じかわからないので、配列全体のサイズを sizeof で取得して、各要素のサイズで割り算することでは要素数を割り出すことができないことがある、という点を意識しておかないといけない。この点を意識した解決方法が、上記サイトにあるやり方だ。このサイトでは、h_addr_list の話をしているけれど、文字列の配列でも有効なはず。
以下のサンプルで試した。

#include <stdio.h>

int main(int argc, char *args[]){
    if( argc > 3 ){
	char **v = args;
	int i = 0;
	for( ; *v != NULL ; v++ ){
	    printf("args[%d] is %s.\n", i, *v);
	    i++;
	}
    }
    return 0;
}

実行結果は以下。

$ gcc stringarray.c
$ ./a.out aaa bbb ccc ddd
args[0] is ./a.out.
args[1] is aaa.
args[2] is bbb.
args[3] is ccc.
args[4] is ddd.
$ ./a.out aaa bbb ccc ddd 888 777 666 333
args[0] is ./a.out.
args[1] is aaa.
args[2] is bbb.
args[3] is ccc.
args[4] is ddd.
args[5] is 888.
args[6] is 777.
args[7] is 666.
args[8] is 333.
$
$ ./a.out aaa b cc dddadgad 88538 777da 666 333ggg
args[0] is ./a.out.
args[1] is aaa.
args[2] is b.
args[3] is cc.
args[4] is dddadgad.
args[5] is 88538.
args[6] is 777da.
args[7] is 666.
args[8] is 333ggg.
$

この書き方なら、各要素の文字列の長さが変わっても対応できる。あと、char *args[] と char **x とは同じ。ポインタと配列は同じ扱いっていうのは頭ではわかっているつもりだが、実際にどうかというと・・・まだ怪しい。これはいろいろなパターンを見て、肌でわかっていくしかない気がする。

あと補足までに、、、v++ というのは、その要素のサイズ分だけメモリを移動する書き方なので、この書き方をすれば必然的に次の要素の先頭にくる、という動作。args[0]のサイズが 3 だったら、args++ は3移動する。args[1]が 2 だったら、args++ は2移動する、という感じだ。各要素のサイズが固定だったら、あらかじめその固定サイズ分移動して、という書き方ができる。要素数で配列の内容を参照する書き方は、意識していようと無意識であろうと、毎回固定サイズ分メモリ参照箇所を移動する書き方ってことだろう。

半年とか一年経過して、自分でこの文章読み返して何を言いたかったかわかるだろうか・・・