Hatena::Groupgeneration1986

仮想化済み古代魚

 | 

2008-05-01

K&R 演習1-13 駄目な例

20:19

 配列全部に0を入れて初期化するにあたってやらかしたミス。コメントにもあるようにint nword[20]で作られるのはnword[0]からnword[19]までであり[20]は作られない。

//	nwordは[0~19]しか存在しない。
	for (i = 0; i <= 20; ++i){	//nword[0~20]を初期化
		printf("変数nword[%d]を初期化\n", i);
		nword[i] = 0;

 実行したら無限ループしました。怖い怖い。

 訂正(hogelogさんのコメントより):無限ループする理由はnword[20]=0はi=0と同じなのでループが0からやり直しになってしまうため。コメントにあるプログラムを実行してみると

&i = 0012FF88, &nword[1] = 0012FF3C
&i = 0012FF88, &nword[2] = 0012FF40
&i = 0012FF88, &nword[3] = 0012FF44
(中略)
&i = 0012FF88, &nword[20] = 0012FF88

となり、iとnword[20]のアドレスが同じになっているのが分かります。そーなのかー。

正しい例

/*K&R P29 演習1-13*/
#include <stdio.h>

#define OUT 0
#define IN 1

int main(void)
{
	int c, state, i;
	int nword[20];			//noword[0~19]
	
	state = c = 0;
	for (i = 0; i <= 19; ++i){	//nword[0~19]を初期化
		printf("変数nword[%d]を初期化\n", i);
		nword[i] = 0;
	}
	
	while ((c = getchar()) != EOF){
		if (c != '\n' && c != '\t' && c != ' '){
			state = IN;
			++i;
		}
		else if (state == IN){	//単語内から外(\n \tスペース)へ出た
			state = OUT;
			++nword[i];	//字数iの単語数++
			i = 0;		//溜まったカウンタをリセット
		}
	}
	
	for (i = 1; i <= 19; ++i){	//ここもnword[20]による無限loop
		printf("[%2d]", i);
		
		for (; nword[i] >= 1 ; --nword[i])
			printf("*");
		
		printf("\n");
	}
	
	return 0;
}

「変数~初期化」はprintfデバッグをやってみた名残。正しくは「配列~初期化」のような気もする。

実行結果

変数nword[0]を初期化
変数nword[1]を初期化
変数nword[2]を初期化
変数nword[3]を初期化
変数nword[4]を初期化
変数nword[5]を初期化
変数nword[6]を初期化
変数nword[7]を初期化
変数nword[8]を初期化
変数nword[9]を初期化
変数nword[10]を初期化
変数nword[11]を初期化
変数nword[12]を初期化
変数nword[13]を初期化
変数nword[14]を初期化
変数nword[15]を初期化
変数nword[16]を初期化
変数nword[17]を初期化
変数nword[18]を初期化
変数nword[19]を初期化
(中略 このプログラムのソースコードをそのままコピペしてみた)^Z
[ 1]**************************
[ 2]*************************
[ 3]**************
[ 4]******
[ 5]*******
[ 6]***
[ 7]**
[ 8]***
[ 9]*
[10]***
[11]**
[12]*
[13]*
[14]*
[15]**
[16]
[17]*
[18]**
[19]

hogeloghogelog2008/05/01 19:22int nword[20];で確保されるのがnword[0-19]までってのはその通りです。ループの範囲をi<=20にしたら無限ループになったっていうのは、nword[20]てのがiと同じ位置を指していて、そこで
nword[20] = 0;
すなわち
i = 0;
としてしまっているからです。こんなプログラム実行してみると、&iと&nword[20]が同じ位置をしめしているのがわかるかと。
#include <stdio.h>
int main() {
int i, nword[20];
for (i = 0; i <= 20; ++i){
printf("&i = %p, &nword[%d] = %p\n", &i, i, &nword[i]);
nword[i] = 0;
}
return 0;
}

oldfisholdfish2008/05/01 20:22>hogelogさん
指摘どうもー。プログラムの実行結果確認したうえで一部追記しておきました。
アドレスとかポインタとか恐ろしいですね

トラックバック - http://generation1986.g.hatena.ne.jp/oldfish/20080501
 |