輝々凛々

ガンバるってことは、素晴らしい事だ。

エンディアンとの闘争2

昨日に引き続き、エンディアンの話。

リトルエンディアンでビットシフト

リトルエンディアン環境の場合、16進数 0x1122 はメモリ上では 0x2211 と格納されています。さて、ここで 16進数 0x1122 を8ビット右シフトすると、結果は 0x0011 となりますが、当然メモリ上では 0x1100 となります。

つまり右ビットシフトした場合、リトルエンディアン環境のメモリ上では、あたかも左ビットシフトしているかのように見えます。これを確認するには、Visual Studioなどのデバッガが必要となります。

リトルエンディアンでマスク

ここで不思議になったのが、リトルエンディアンでのマスク。マスク・・、つまり「0x1122 & 0xff」とやったときの挙動が気になりました。結果はもちろん「0x0022」となるのですが・・・

まず16ビット型(short/__int32)の変数valueに0x1122を入れておきます。リトルエンディアン環境でのvalueのメモリ状態は0x2211となっています。

このvalueと0xffとのマスクをとります。

value = value & 0xff;

こうすると、結果はもちろん「0x0022」です。が、、よくよく考えると、C言語では定数を直書きした場合、int型として扱われます。そのため単に「0xff」と書いたものは、int型(32ビット)として扱われているはずです。

ということは、、0xffのメモリ上の配置は「0xff000000」となっているはずです。これでマスクを取ったら、結果は0x00になりそうなものです。

ところが、C言語では、整数型は必要に応じてビット数を昇格してもいいという決まりがあります。つまり「0xff000000」とマスクを取るshort型の変数valueは、マスク値が32ビットの整数型だから、一時的にvalueを32ビットに昇格することができます。

つまり、結局「value & mask」を行うときは、メモリ上では「0x22110000 & 0xff000000」という計算を行っています。この結果は、当然「0x22000000」になります。

そして昇格していたビット幅を元に戻して「0x2200」となり、それが最終的にvalueに代入されるようです。

まとめ

そんなこんなで、ビットシフトとマスクにおけるエンディアンの状態を考えてみました。普段はメモリ上にしか現れないので気にしなくても良いです。まぁメモリ上のデータをデバッグするような機会があれば参考になるかもしれません。

という程度のメモで以上。

関連記事

ツッコミの投稿


(ツッコミ非公開の場合はチェック)