読者です 読者をやめる 読者になる 読者になる

WGC1 第3章2進数の算術演算子とビット演算 3.4シフトとローテート

C

  • 左シフトでは、最上位ビットの値は、この演算のキャリーアウト(桁上げ出力)になる
  • 右シフトでは、第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







Randall Hyde、鵜飼 文敏、まつもと ゆきひろ、後藤 正徳、トップスタジオ