WGC1 第3章2進数の算術演算子とビット演算 3.4シフトとローテート
- 左シフトでは、最上位ビットの値は、この演算のキャリーアウト(桁上げ出力)になる
- 右シフトでは、第0ビットの値は、この演算のキャリーアウトになる
- 算術右シフトでは、最上位ビットの値は、変更されない
通常はこれにより、2の補数の符号付オペランドに対して、予想したとおりの結果が得られる。
ただし、この演算には、常に値が丸められるという注意点がある
実際の結果以下で、かつ実際の結果に最も近い整数になる。
たとえば、-1($FF)を算術右シフトすると結果は0ではなく、-1となる。-1は0未満の値なので
算術右シフト演算では、-1の方向に丸められる。
実験コード
#include <stdio.h> #include <stdlib.h> int main(int argc, char* argv[]){ unsigned int ui = 64; int i = 64; int minus = -64; unsigned int u_result = 0; int result = 0; int bit30 = 0; int bit3031 = 0; /* shift left operation */ printf("shift left operation\n"); u_result = ui << 1; result = ui << 1; printf(" ui unsigend result =%hd\n", u_result); printf(" ui result =%d\n", result); u_result = i << 1; result = i << 1; printf(" i unsigend result =%hd\n", u_result); printf(" i result =%d\n", result); u_result = minus << 1; result = minus << 1; printf(" minus unsigend result =%hd\n", u_result); printf(" minus result =%d\n", result); /* shift right operation */ printf("shift right operation\n"); u_result = ui >> 1; result = ui >> 1; printf(" ui unsigend result =%hd\n", u_result); printf(" ui result =%d\n", result); u_result = i >> 1; result = i >> 1; printf(" i unsigend result =%hd\n", u_result); printf(" i result =%d\n", result); u_result = minus >> 1; result = minus >> 1; printf(" minus unsigend result =%hd\n", u_result); printf(" minus result =%d\n", result); bit30 = ( ui & 0x08000000 != 0) ? 0x40000000 : 0; u_result = (ui & 0x7FFFFFFF ) >> 1; u_result = u_result | bit30; bit30 = ( ui & 0x08000000 != 0) ? 0x40000000 : 0; result = (ui & 0x7FFFFFFF ) >> 1; result = result | bit30; printf(" ui unsigend result =%hd\n", u_result); printf(" ui result =%d\n", result); bit30 = ( i & 0x08000000 != 0) ? 0x40000000 : 0; result = (i & 0x7FFFFFFF ) >> 1; result = u_result | bit30; bit30 = ( i & 0x08000000 != 0) ? 0x40000000 : 0; result = (i & 0x7FFFFFFF ) >> 1; result = result | bit30; printf(" i unsigend result =%hd\n", u_result); printf(" i result =%d\n", result); bit30 = ( minus & 0x08000000 != 0) ? 0x40000000 : 0; result = (minus & 0x7FFFFFFF ) >> 1; result = u_result | bit30; bit30 = ( minus & 0x08000000 != 0) ? 0x40000000 : 0; result = (minus & 0x7FFFFFFF ) >> 1; result = result | bit30; printf(" minus unsigend result =%hd\n", u_result); printf(" minus result =%d\n", result); /* Arithmetic shift right operation */ printf("Arithmetic shift right operation\n"); bit3031 = ( ui & 0x08000000 != 0) ? 0xC0000000 : 0; u_result = (ui & 0x7FFFFFFF ) >> 1; u_result = u_result | bit3031; bit3031 = ( ui & 0x08000000 != 0) ? 0xC0000000 : 0; result = (ui & 0x7FFFFFFF ) >> 1; result = result | bit3031; printf(" ui unsigend result =%hd\n", u_result); printf(" ui result =%d\n", result); bit3031 = ( i & 0x08000000 != 0) ? 0xC0000000 : 0; u_result = (i & 0x7FFFFFFF ) >> 1; u_result = u_result | bit3031; bit3031 = ( i & 0x08000000 != 0) ? 0xC0000000 : 0; result = (i & 0x7FFFFFFF ) >> 1; result = result | bit3031; printf(" i unsigend result =%hd\n", u_result); printf(" i result =%d\n", result); bit3031 = ( minus & 0x08000000 != 0) ? 0xC0000000 : 0; u_result = (minus & 0x7FFFFFFF ) >> 1; u_result = u_result | bit3031; bit3031 = ( minus & 0x08000000 != 0) ? 0xC0000000 : 0; result = (minus & 0x7FFFFFFF ) >> 1; result = result | bit3031; printf(" minus unsigend result =%hd\n", u_result); printf(" minus result =%d\n", result); return 0; }
コンパイル
[oc@centos5 shift]$ gcc shift.c -o shift
結果
[oc@centos5 shift]$ ./shift shift left operation ui unsigend result =128 ui result =128 i unsigend result =128 i result =128 minus unsigend result =-128 minus result =-128 shift right operation ui unsigend result =32 ui result =32 i unsigend result =32 i result =32 minus unsigend result =-32 minus result =-32 ui unsigend result =32 ui result =32 i unsigend result =32 i result =32 minus unsigend result =32 minus result =1073741792 Arithmetic shift right operation ui unsigend result =32 ui result =32 i unsigend result =32 i result =32 minus unsigend result =-32 minus result =1073741792