構造体のshort型のメンバ配列変数の表示について

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
こめかみ

構造体のshort型のメンバ配列変数の表示について

#1

投稿記事 by こめかみ » 16年前

cygwinで下記のコードをコンパイルして実行し、
例えば4回とも

"1"

を入力すると。

↓このように表示されて欲しいのですが、

A点:(1,1)
B点:(1,1)

実際には

↓このようにA点のy座標が0で出力されてしまいます。

A点:(1,0)
B点:(1,1)

int型だとこの問題は起きません、

また、B点の座標の入出力をカットすると、short型でもうまく表示されます。

何が起きているのでしょうか、調べ方などアドバイスよろしくお願いします。

#include <stdio.h>

typedef struct{

	short x[2];//x座標
	short y[2];//y座標
	//short area;//面積

} cordinate_t;


int main()
{
	cordinate_t cord;


	puts("A点");
	printf("X座標:");	scanf("%d", &cord.x[0]);
	printf("Y座標:");	scanf("%d", &cord.y[0]);

	puts("B点");
	printf("X座標:");	scanf("%d", &cord.x[1]);
	printf("Y座標:");	scanf("%d", &cord.y[1]);


	printf("A点:(%d,%d)\n", cord.x[0], cord.y[0]);
	printf("B点:(%d,%d)\n", cord.x[1], cord.y[1]);

	return 0;
}

ちなみに構造体に面積の変数があるのは本来このようなプログラムだったからです。
#include <stdio.h>

typedef struct{

	short x[2];
	short y[2];
	short area;

} cordinate_t;


int main()
{
	cordinate_t cord;
	short m;
	cord.area = 0;

	while (1){

		printf("面積:%d\n", cord.area);
		printf("座標を変更しますか? 【Yes…1/No…0】:\n");
		scanf("%d", &m);

		if (!m){ break; }

		puts("左下");
		printf("X座標:");	scanf("%d", &cord.x[0]);
		printf("Y座標:");	scanf("%d", &cord.y[0]);

		puts("右上");
		printf("X座標:");	scanf("%d", &cord.x[1]);
		printf("Y座標:");	scanf("%d", &cord.y[1]);


		if ( cord.x[0] > cord.x[1]  ||  cord.y[0] > cord.y[1] ){
			puts("右上は左下よりも大きくしてください");
			continue;
		}

		printf("左下:(%d,%d)\n", cord.x[0], cord.y[0]);
		printf("右上:(%d,%d)\n", cord.x[1], cord.y[1]);

		cord.area = (cord.x[1] - cord.x[0]) * (cord.y[1] - cord.y[0]);

	};

	return 0;
}

toyo

Re:構造体のshort型のメンバ配列変数の表示について

#2

投稿記事 by toyo » 16年前

scanf("%d", &cord.x[0]);
が間違いです。
short型への読み込みには
scanf("%hd", &cord.x[0]);
を使います。
coordinate_t構造体にshort型メンバが4個として
x0   x1   y0   y1
???? ???? ???? ????
のようにメモリ確保されたとします。(??で1バイト)
初期化してないので??にしています。
scanf("%d", &cord.x[0]);
で1が入力されるとするとint型として代入されるので
x0   x1   y0   y1
0100 0000 ???? ????
のようにx1の領域まで代入されます(リトルエンディアンなので01が最初になっています)
以下同様に1が入力されるとして
scanf("%d", &cord.y[0]);
x0   x1   y0   y1
0100 0000 0100 0000

scanf("%d", &cord.x[1]);
x0   x1   y0   y1
0100 0100 0000 0000 *y0が0に書き換えられる

scanf("%d", &cord.y[1]);
x0   x1   y0   y1
0100 0100 0000 0100 0000 *スタックオーバーフロー
表示の際はshortなので
x0 = 1
y0 = 0
x1 = 1
y1 = 1
と表示されます。
(スタックオーバーしてるのでエラーになるかもしれません)
x1の入力に0x00010001(65537)を入力して全部1になるのを確認してみましょう

toyo

Re:構造体のshort型のメンバ配列変数の表示について

#3

投稿記事 by toyo » 16年前

追伸
printf( )でもshortの表示には h をつけましょう
(%hd, %hx)

toyo

Re:構造体のshort型のメンバ配列変数の表示について

#4

投稿記事 by toyo » 16年前

スタックオーバーフローじゃなくてバッファオーバーフローですかね

cygwinでコンパイルされてるそうですが
$ gcc -Wall sample.c
のように警告表示オプションをつけるとフォーマット指定と引数の型が違うときに警告を出してくれますよ。

こめかみ

Re:構造体のshort型のメンバ配列変数の表示について

#5

投稿記事 by こめかみ » 16年前

toyoさん
大変詳細な解説ありがとうございました。

short int型もint型と同じ変換指定子と勘違いしてました。


コンパイルオプションですか、
調べたらたくさんあってなかなか使いこなせなそうですが、
少しずつ試してみようと思います。

cygwinは去年、C言語を授業で習いはじめるにあたって、
闇雲にインストールしたものなので、
さっぱり使いこなせて無いようです。

UNIXについてももう少し調べてみようと思います。


>>スタックオーバーフローじゃなくてバッファオーバーフローですかね

違いがよくわからなかったので調べてみましたところ、
http://ja.wikipedia.org/wiki/%E3%82%B9% ... D%E3%83%BC

スタックオーバーフローは、バッファオーバーフローの一種だそうです。

認識の曖昧な用語が次々出てきて大変です…
勉強させていただきます。

閉鎖

“C言語何でも質問掲示板” へ戻る