C exercises2 (2) bitwise

第9章 ビットを意識する

整数型の指定

整数値を扱うための型には,( signed, unsigned ) char 型と int 型とがあることは説明したが, それら以外にもある.ここで,まとめて簡単に解説する.

バイト数 ビット数 最小値 最大値
unsigned char 1 8 0 255
signed char 1 8 -128 127
unsigned short int 2 16 0 65535
signed short int 2 16 -32768 32767
unsigned int 4 32 0 4294967295
signed int 4 32 -2147483648 2147483647
unsigned long int 4 32 0 4294967295
signed long int 4 32 -2147483648 2147483647
unsigned long long int 8 64 0 18446744073709551615
signed long long int 8 64 -9223372036854775808 9223372036854775807

基本的な整数型には char, short int , int, long int, long long int の4種類があり,そのサイズは char ≦ short int ≦ int ≦ long int ≦ long long int となる.

char 型は 1 バイトであると決まっているが,あとの種類はサイズが厳密に決められたものではなく, 将来は変わる可能性がある. 実際に,数年前のパソコンは 16ビットマシンが多かったので, int 型は 16ビット=2バイトであった.

今使っているコンピュータの環境では,たまたま int 型と long int 型とは,まったく同じものとなっている.

浮動小数点型の指定

 

バイト数 ビット数 最小値 最大値
float 4 32 1.175494 10-38 3.402823 10+38
double 8 64 2.225074 10-308 1.797693 10+308

 

float型

float型は4バイト=32ビットのサイズを持ち,そのビットを次のように,符号,指数,仮数を表すために用いる.

float型の内部表現指数部-127 が指数の値となる.仮数部は仮数の小数点以下を表している.すなわち,仮数は仮数部の先頭に 1. を付加したものになる.

 

float の表す値 = (-1)符号部 × 2指数部-127 × 1.仮数部

float 型の精度(有効桁数)は2進数にして 24 (=23+1) 桁であり,10進数では約 7 桁となる.

double 型

float 型に比べて,約倍の精度をもった浮動小数点型の型が double である. double 型は 8バイト=64ビットのサイズであり,その内部表現は次のようになる.

double型の内部表現指数部-1023 が指数の値となる.仮数部は仮数の小数点以下を表している.すなわち,仮数は仮数部の先頭に 1. を付加したものになる.

 

double の表す値 = (-1)符号部 × 2指数部-1023 × 1.仮数部

double 型の精度(有効桁数)は2進数にして 53 (=52+1) 桁であり,10進数では約 15 桁となる.

Sizeof演算子

簡単に言うと,sizeofに渡された型や変数のメモリサイズを調べるものです.

sizeof演算子は2種類の使い方があります.

  • sizeof(型)
  • sizeof 変数や定数,あるいは式など

ビット演算子

ビット単位でデータ操作をするものです。対象は整数に限られます

【ビット演算子】
演算子 説明
 & ビットごとの AND
 | ビットごとの OR
 ^ ビットごとの XOR
 ~ ビットごとの反転(1 の補数)
 << 左シフト
 >> 右シフト

(1) & (and)

両方のビットが 1 のときのみ結果が 1 になるビット演算です。

0 & 0 → 0
0 & 1 → 0
1 & 0 → 0
1 & 1 → 1

必要なビット以外をOFF(0)にする処理(マスクといいます)に使用されます。

例えば、10101010 という1バイトのビット列の下位4ビットを OFF する場合、そのままにしたいビットを 1 、OFFしたいビットを 0 にした、11110000 で and することにより実現できます。

(使用例)

unsigned char a = 0xaa;	/*     10101010 */
printf("%#xn",a & 0xf0);	/* and 11110000 */

実行結果
0xa0

(2) | (or)

いずれかのビットが 1 なら結果が 1 になるビット演算です。

0 | 0 → 0
0 | 1 → 1
1 | 0 → 1
1 | 1 → 1

必要なビットをON(1)にする場合に or は使われます。

例えば、10101010 という1バイトのビット列の上位4ビットを ON する場合、ONにしたいビットを 1 、そのままにしたいビットを 0 にした、11110000 で or することにより実現できます。

(使用例)

unsigned char a = 0xaa;	/*    10101010 */
printf("%#xn",a | 0xf0);	/* or 11110000 */

実行結果
0xfa

(3) ^ (xor)

両方のビットが異なるときに結果を 1 にするビット演算です。

0 ^ 0 → 0
0 ^ 1 → 1
1 ^ 0 → 1
1 ^ 1 → 0

特定なビットを反転する場合に xor は使われます。

例えば、10101010 という1バイトのビット列の下位4ビットを反転する場合、反転したいビットを 1 、そのままにしたいビットを 0 にした、00001111 で xor することにより実現できます。

(使用例)

unsigned char a = 0xaa;	/*     10101010 */
printf("%#xn",a ^ 0x0f);	/* xor 00001111 */

実行結果
0xa5

(4) ~ (補数)

ビットの反転を行うビット演算です。

0 → 1
1 → 0

全ビットの無条件反転を行います。

(使用例)

unsigned char a = 0xaa;	/*     10101010 */
printf("%#xn",~a);

実行結果
0xff55		
(注)printf関数が unsigned char型を int型に符号拡張するために、0xff55 と表示されます。
   int型が4バイトの処理系では 0xffffff55 になります。

(5) << (左シフト)

x << n と書き、x を n ビット左へシフトします。

右側の空いたビットには 0 が入り、左側のビットは捨てられます。

左シフトは x が正の場合、x << 1 で「x * 2」を計算することと同じになります。

(例)

正の整数のとき

int x = 100;

x = x << 2;

(6) >> (右シフト)

x >> n と書き、x を n ビット右へシフトします。

左側の空いたビットには、x が符号無しなら 0 が入ります。x が符号付きなら、算術シフトを行う処理系では符号桁が入り、論理シフトを行う処理系では 0 が埋められます。 右側のビットは算術シフト、論理シフトにかかわらず捨てられます。

右シフトは x が正の場合 x >> 1 で「x / 2」を計算することと同じになります。

(例)

正の整数のとき

int x = 100;

x = x >> 2;

負の整数のとき(算術シフトを行う処理系の場合)

int x = -100;

x = x >> 2;

【参考】

  • 算術シフト:数値の演算を行うときに使用するシフト演算で、シフトの際に最上位の符号ビットを保存するシフトです。
  • 論理シフト:ビットの位置を変えるときに使用するシフト演算で、シフトの際に最上位の符号ビットを考慮することなくシフトを行います。

演習

1)任意二つのunsigned int型数値の論理AND, OR, XORを求めなさい(P324)

2)任意unsigned int型数値のビットパターンを表示(P328)