環境固有の問題?それとも…

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

環境固有の問題?それとも…

#1

投稿記事 by ミヤ » 16年前

はじめまして、ミヤともうします。
まだ初心者なのでプログラムではなくて環境等の問題かもしれないのですが、、
どうにも自力で(友人に聞いても)解決できない壁にぶつかったので質問させていただきます。


<問題点>
特定箇所のprintf()関数において%xで表示させる数値が32bit(4バイト)分表示され
変数のサイズを越える部分が'f'で埋められる


<状況>
C言語プログラム(本文末尾に出力結果とともにペースト)をBCC ver.5.5で
コンパイルしてWindows XP Home上のMS-DOSプロンプトで実行すると、
添付画像ならびに文末画面出力2行目の指示して無い文字
("0xffffff80"の"fffff")が出力される。

コンパイルはエラーもなくできます。

sizeof(chr_y)を表示させても1としか表示されない。
変数の型を変更した場合、
(signed char)の場合は0xffffff80
(signed short int)の場合は0xffff8000
といった具合に、単純に変数を表示しているだけなのですが、
どういうわけか符号付整数において先頭(符号)ビットに1が立って
他のビットが0の場合だけに表示がおかしくなるのかな・・・。


'f'ではなく'0'なら"%08x"とかいたかな・・とかわかるのですが。。。


<環境>
WindowsXP Home (SP2) (i386)
BCC32.exe(Version 5.5)


<希望>
勝手に出てくる文字'f'を表示しない方法がお分かりになる方が
いらっしゃいましたらご指南いただきたく思います。

又は、手元の環境では問題が無いという方がいらっしゃいましたら、
参考までに教えていただけますでしょうか?


<以下ソースとか画面に表示される内容>
----プログラムここから----
#include<stdio.h>

//10進と16進で数字を表示するプログラム

int main(void){
	signed char chr_x, chr_y;
	unsigned char uchr_x, uchr_y;
	chr_x = uchr_x = 0x7f;
	chr_y = uchr_y = 0x80;
	printf("in case of signed char\n");
	printf("  0x%x + 0x01 = 0x%x \n", chr_x, chr_y);
	printf("   %d +    1 = %d \n\n", chr_x, chr_y);
	printf("in case of unsigned char\n");
	printf("  0x%x + 0x01 = 0x%x \n", uchr_x, uchr_y);
	printf("   %d +    1 =  %d \n\n", uchr_x, uchr_y);
	return(0);
}
----プログラム終わり----

----出力結果ここから-----
in case of signed char
  0x7f + 0x01 = 0xffffff80
   127 +    1 = -128

in case of unsigned char
  0x7f + 0x01 = 0x80
   127 +    1 = 128


----出力結果終わり----

toyo

Re:環境固有の問題?それとも…

#2

投稿記事 by toyo » 16年前

%xはint型で表示するので必ず4バイト分表示されます
char型を引数にしてもint型に拡張されてから表示されるため負の値の時は拡張されたビットがすべて1
になります。char型の0x80は-128でint型の-128は0xffffff80
フォーマットにhhが使えるコンパイラなら %hhx で表示すれば1バイト分のみ表示できます。

Mist

Re:環境固有の問題?それとも…

#3

投稿記事 by Mist » 16年前

表示のときだけunsigendにキャストするのもひとつの方法です。

printf(" 0x%x + 0x01 = 0x%x \n", (unsigned char)chr_x, (unsigned char)chr_y);

non

Re:環境固有の問題?それとも…

#4

投稿記事 by non » 16年前

こうすることも可。
printf(" 0x%x + 0x01 = 0x%x \n", chr_x, chr_y & 0xff);

ミヤ

Re:環境固有の問題?それとも…

#5

投稿記事 by ミヤ » 16年前

お返事いただいた皆様ありがとうございます。
友人に聞いてももやもやした返答しかえられず困っていたのがこれですっきりいたしました。
大変申し訳ありませんが部分引用にて返信させていただきます。


toyo様
>%xはint型で表示するので必ず4バイト分表示されます
>フォーマットにhhが使えるコンパイラなら %hhx で表示すれば1バイト分のみ表示できます。

早速試してみました。
詰まるところ(int)に型変換して表示している状態だったのですね。
それで左のビットに1が並んでいたのも納得です。
残念ながら手元の環境(Winxp/bcc)においてはご教授いただいた方法では
1バイト分の表示とはなりませんでした。ただし、 %hx で2バイト分の表示に変わりました。
(short int)を扱うときには有効に使えそうなのでぜひ活用させていただきます。



Mist様
>表示のときだけunsigendにキャストするのもひとつの方法です。

早速試してみました。
なるほど、否負の整数であれば値が1となるビットまでの表示を省略するって事なんですね。


non様
>printf(" 0x%x + 0x01 = 0x%x \n", chr_x, chr_y & 0xff); //このようにすることも可

早速試してみました。
出力としては期待した結果を得ることができました。
しかし、理解力が足りないためかもともと1バイト分しかない整数に1バイトとして
明示的にマスクを掛けることで何故期待した表示が得られるのか・・・とても疑問です。

non

Re:環境固有の問題?それとも…

#6

投稿記事 by non » 16年前

>しかし、理解力が足りないためかもともと1バイト分しかない整数に1バイトとして
>明示的にマスクを掛けることで何故期待した表示が得られるのか・・・とても疑問です。

chr_y & 0xffの計算をする段階でint型(BCCなら4バイト)に変換される。
すなわち、計算は上位の型にあわせられて計算される。(0xffはint型、0x000000ffと同じ)
従って
0xffffff80 & 0x000000ff = 0x00000080 になる。
表示の時、上位の0は表示されないので80のみ表示される。

なお、%hhはC99で拡張された機能なので、BCでは不可。%hはOKです。

ミヤ

Re:環境固有の問題?それとも…

#7

投稿記事 by ミヤ » 16年前

non様

丁寧な解説ありがとうございます。
char型の負数がint型負数として扱われる際に
1でつめられたビットを0にセットしなおす事で
キャストした際と同じ結果をもたらすということですね。

お手間を掛けてすみませんでした。

また、%hhに関するご指摘を元にキーワード"C99"で調べたところ
コンパイラの準拠するバージョンによる違いがあることが分かり
環境によって依存するソースを書いて、違う環境(学校と自宅の間等)に
持っていったときに期待しない動きにならないように注意するべきと実感いたしました。


ご回答いただいた皆様改めてありがとうございました。

9月から本格的に始まる授業等で分からないことがあったときに、改めて
質問させて頂く事が在ると思いますがなにとぞよろしくお願いいたします。

閉鎖

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