二重のポインタとか、char型についてとか

久しぶりの投稿。


早速ですが、以下のソースを。

#include <stdio.h>

int main(){

	int a=200,b=300,*p,**q,*ql;

	p=&a;
	ql=&b;
	q=&ql;

	printf("&a = %p\n",&a);
	printf("&b = %p\n",&b);
	printf("*p = %d\n",*p);
	printf("p = %p\n",p);
	printf("*ql = %d\n",*ql);
	printf("ql = %p\n",ql);
	printf("**q = %d\n",**q);
	printf("*q = %p\n",*q);
	printf("q = %p\n",q);
	return 0;
}

1年次のときの課題の内容です。
これが何をやっているかってのは、どうしても習っていた当初は分からなかったです。
不真面目な時期でもありましたし(汗)
昨日同学年の友人と話をして再認識をしたっていう形ですね。
頭で分かっていても、やっぱり人と確認をするっていうのは大事なんだな、と。
理解が深まります。

さて、これを実行すると以下の様な出力となります。

% ./a.out 
&a = 0x7fff5fbff6ac
&b = 0x7fff5fbff6a8
*p = 200
p = 0x7fff5fbff6ac
*ql = 300
ql = 0x7fff5fbff6a8
**q = 300
*q = 0x7fff5fbff6a8
q = 0x7fff5fbff6a0

この課題のミソって、二重ポインタの部分なんだろうなぁ、と。
**qですね。
*qにもqにもアドレスが入っているという形。う〜ん。厄介。
でもこれも大事な考え方ですね。というお話なんじゃないのかと。


さて、今回の本題に。
まずは下のソースを見て下さい。

#include <stdio.h>

int main(){

	char str[3] = "asdfgh";
	int i;

	printf("str = %s\n",str);
	printf("入力 -> "); scanf("%s",str);
	printf("%s\n",str);

	return 0;
}

これを実行してみると(warningが起こりますが、今はあまり気にしない)

% ./a.out 
str = asd
入力 -> asdfghj
asdfghj

こんな感じになります。
ここで不思議なことに、str[3]と宣言しているのに、scanfで読み取った7文字全てがしっかりstrに格納されている、ということが...。

これを先生に質問してみたところ、ボクとはちょっと違った点が問題点としてあげられました。
その内容が
「%s出力というのはNULL文字までを表示するものだから、出力の1行目が3文字なのはおかしい」
というものでした。
「勝手に4文字目がNULLに置き換わっているのかも...」

ということだったので、少しソースを改変してもう一度実行。
この改変したものが以下の通り

#include <stdio.h>

int main(){

	char str[3] = "asdfgh";
	int i;

	for(i = 0; i < 7; i++){
	printf("str[%d] = %c\n",i,str[i]);
	}
	scanf("%s",str);
	printf("%s\n",str);

	return 0;
}

今度は、strを%cで1文字ずつ出力するようにしました。
すると、実行結果は以下の通り。

% ./a.out 
str[0] = a
str[1] = s
str[2] = d
str[3] = 
str[4] = 
str[5] = 
str[6] = 
入力 -> asdfgh
asdfgh

先生の言っていた通り、4文字目がNULL文字になっていました。
この部分、もう少ししっかり調べてみると面白いのかも知れない...?

という感じです。まだ自分の技量不足であまりちゃんと書けてないと思いますけど。
今後、この辺り調べてみます。