#pragma twice

KAB-studio > プログラミング > #pragma twice > 056 Version 4.06 正と負!

#pragma twice 056 Version 4.06 正と負!

前のページへ 表紙・目次へ 次のページへ

 Version 4.06
正と負!

ビット編最後は〈正と負〉について
それってプラスとマイナスのこと?
そう。さて、まずはおさらいから。 char って16進数何桁入るんだっけ
2桁だよ。 0x11 みたいな感じ
16進数1桁は、2進数で何桁だっけ
4桁。 0x5 が 0101 みたいな。ってことは、 char は2進数8桁分って
ことだね、 01010101 が 0x55 で、えーっと…… 85 みたいに
そういうこと。それを踏まえて、次の関数を試してみましょう

void BitShift8()
{
    char ch = 0x01; // 00000001
    for( int iF1 = 0; iF1 < 8; iF1++ )
    {
        TRACE( "%d ", ch );
        ch = ch << 1;
    }
}
// 1 2 4 8 16 32 64 -128 

あ、この前見たのと似てるね
この前は4回しかシフトしなかったけど、今回は8回、だから 00000001
から 10000000 までシフトする例
 00000001 が 1 で、 00000010 が 2 で、そのあと 4 8 16 32 64 -128
って、なんで 128 だけマイナスなの!? あ、これがミソなんだ
そういうこと。 char の変数は、サイズが8ビット。どうがんばっても、
8ビット分の情報しか入らない
8ビットって、メモリの1マスだもんね。もしはみ出たら、他の変数にと
か邪魔しちゃうかもしんないもんね
単純に、 11111111 つまり 0xFF を10進数に直すと?
 16 * 15 + 15 だから 255 だね
ってことは、 00000000 から 11111111 まで全部使うと、 0 から 255 ま
で表せるってことだ
そだね
マイナスはどうする?
あ、そういえば
〈この数はマイナスですよ〉っていう情報も、8ビットの中に入れなきゃ
いけないでしょ。それをどうするか
どうするの?
そこで、ビットひとつを〈プラスかマイナスかのフラグ〉にする、ってこ
とになります。そのフラグは一番左の桁。 00000000 だとプラス、 10000000
だとマイナスね
あ、 10000000 ってだから -128 だったんだ!
そういうこと。一番左の桁を正負のフラグにして、あとの7桁を数字を表
すのに使います
ってことは、正の数は 01111111 まで……だから 127 まで表せるってこ
とだね。う”、一気に半分になっちゃった
その分、マイナスも表せるってことだからね
……変よ! なんで 10000000 が -128 なの? -0 とか -1 とかなりそ
うなのに
 -0 はないでしょ。 -1 は 11111111 だよ。で、 -2 は 11111110 ね
えーっ!? 逆になるんだー、なんかわけわかんない……
分かんなくていいよ、これは計算する必要とかあんまりないから
そなの?
そなの。しっかり憶えて欲しいのは、一番左の桁が正負のフラグってこと
確かにこれは、知ってないと怖いよね
ちなみにマイナスの最大値は -128 だから
あー、 11111111 から減らしていけば 10000000 になって -128 になるも
んね。さらに減らすと 01111111 で 127 になっちゃうし
そういうこと。 char 型変数の中に入るのは 127 から -128 ってことだね
あ! これが Ver 4.02 ( No.052 )で言ってた〈 -128 から 127 の間
の数字しか、 char 型変数には入らないから〉の理由なんだ!
そういうこと。理由が分かるって大事だからね
うん、こーゆーの分かるのうれしいもん
さてさて、 char は 127 から -128 しか使えないけど、実は 255 から 0
まで使う方法があります
それって一番左の桁を正負のフラグに使わない、ってことだね?
そゆこと。そういうのを〈符号なし整数値〉って言います
プラスだけなんだ
限界ギリギリの数字を使いたいときや、純粋にビットフラグだけとして使
いたいときによく使われるかな。じゃ、まずこれから

void Normal()
{
    char ch = 255;
}

あ、ビルドしたらエラー出た

warning C4305: 'initializing' : 'const int'から'char'へ切り詰めます。
warning C4309: 'initializing' : 定数値が切り捨てられました。

エラーじゃなくて警告だね。一応 char 型に 255 は入るんだけど、 char 
の範囲内じゃないから切りつめられちゃうわけ
だから〈あかんよー〉って言ってるんだ
では次

void Signed()
{
    signed char ch = 255;
}

warning C4305: 'initializing' : 'const int'から'char'へ切り詰めます。
warning C4309: 'initializing' : 定数値が切り捨てられました。

同じエラー出た。あれ、 signed って?
これは〈さいんど〉って読みます。これが付いていると〈符号あり〉って
見なされます。だから signed char には 127 から -128 まで入るってこと
だね
……それってこれまでと一緒じゃん
そゆこと。ただ、それは VC だから
どゆこと?
開発環境によっては、デフォルトが signed とは限らないからね。 VC は
何も付けないと自動的に signed が付いたのと同じになるってこと
前もそーゆーのあったね
プログラミングにはそういうのがつきものだから注意してね。では本命、
符号なし整数値です!

void UnSigned()
{
    unsigned char ch = 255;
    TRACE( "%u\n", ch );
    // 255
}

あ、 unsigned ってのがそうなんだ
そう、これは〈アンサインド〉って読んで、これが付くと〈符号なし〉に
なります。だからこれは警告が出ません
ほー。あれ、 TRACE() が %u になってる
 %d は〈符号あり整数〉として表示するのだからね。〈符号なし〉として
表示するのは %u の方
ちょっと複雑ねー
まーね。この辺は実際複雑だから
どゆこと?
 signed char に -1 入れるのと、 unsigned char に 255 入れるのって、
ビット的には同じでしょ
うん、どっちも 11111111 だよね
つまりこれは〈符号あり〉ってみなすか〈符号なし〉って見なすかの問題
ってことだね
みなしの問題、つまりどう捉えるか、どういうものなのかって考えるかっ
てことだよね
たとえば

void Compare()
{
    char ch = -1;
    unsigned char uch = ch;

    if( ch < uch )
    {
        TRACE( "%d < %u\n", ch, uch );
    }
}
// -1 < 255

あ、 char のを unsigned char に入れてるんだ。で、 if で比べて……
そっか、 unsigned char のに入れると -1 が 255 になっちゃうから、そっ
ちの方が大きくなっちゃうんだ
ビット的には同じだけど、〈型〉が違うから比較方法が変わっちゃうんだ
よね
型?
そう。 int とか char とか unsigned char みたいな〈変数を作るときに、
その変数がどんな性格か〉を決めるものを〈型〉っていいます
つまり、 char と unsigned char は、メモリの上じゃおんなじ1マスな
のに、 char はマイナスあり、 unsigned char はマイナスなしってゆー
ふーに、性格が変わるってことね
そういうこと。 < なんかの演算子は、掛かる変数がどんな型かで比較方
法が変わるわけ。今の例みたいにね
プログラミングはみなしの世界。型はその〈どうみなすか〉を決めるもの
だから、大事ってことよね
そういうことだね。この部分、とっても大事だから
そんなに大事?
大事だね。こういう部分に問題が起きやすいから
たとえば?
たとえば今の比較の問題。後から出てくるけど、普段は char の方がよく
使うのに、実際の処理は unsigned char の方がよく使うとかあるんだよね
どゆこと?
入ってる数字は 0 から 255 なのに、それ入れるのは char の変数ってこ
と。こういうとこ勘違いするとあいたーってことになりかねないからね
そういうのの対処法は?
どこが問題になりやすいのかってことを気にしておくことだね。符号問題
は、比較が一番の問題点だから、比較するときに気を付けるとかね
 < を使う時に〈あ、符号大丈夫かな〉って考えるんだ
あとは余裕だね。 255 まで入るから unsigned char ってよりは、 int 
使っちゃう方がいいとかね
なるほど、余裕持たせれば面倒なこと考えなくていいんだ
実際にはそう簡単には割り切れないし、どういう場面でどっちを使えばい
いって議論はずっとされてきてて、決着が付いてなかったりするんだよね
つまり〈これすればOK!〉みたいなのってないってこと?
そういうこと。火美ちゃんは、今日教えた〈みなしの世界〉ってどう思
う?
ヘン! ってゆーかアブナイ、かな。たとえばさ、1って、1等ならいい
けど、成績で1って良くないじゃん、そーゆーふーに、場合場合で意味変わ
るのってなんか怖いな
その怖い世界がプログラミングの世界。そういう点を自覚するのも、大事
かな
なんかヤバイ世界に足突っ込んだ?
1年経って何を今さら

/*
    Preview Next Story!
*/
ってことはさ、世の中のコンピューターって、全部こんな感じ?
こんな感じ
うわー、なんかそう考えると怖いね
って、火美ちゃんだってこんな感じじゃん
ひーそうだったー!
というわけで次回
< Version 4.07 short とバイトオーダー >
につづく!
火美ちゃんもみなしの世界に生きてるんだよ
……じゃー水希ちゃんを美形ってみなすこともできるんだ
おい
 
del.icio.us 登録する
Yahoo!ブックマーク 詳細を表示 users
livedoorクリップ 詳細を表示 livedoorクリップ ブックマーク数
はてなブックマーク 詳細を表示 はてなブックマーク ブックマーク数
RSSに登録
del.icio.us 登録する
Yahoo!ブックマーク 詳細を表示 users
livedoorクリップ 詳細を表示 livedoorクリップ ブックマーク数
はてなブックマーク 詳細を表示 はてなブックマーク ブックマーク数
 
このページは、Visual C++ 6.0を用いた C++ 言語プログラミングの解説を行う#pragma twiceの一コンテンツです。
詳しい説明は#pragma twiceのトップページをご覧ください。