在 C 語言中使用位移操作

Jinku Hu 2023年1月30日 2021年2月28日
  1. 在 C 語言中使用 << 運算子將數字向左移位的方法
  2. 在 C 語言中使用左移位來實現整數乘以二的計算
  3. C 語言中的右移-算術與邏輯移位的區別:
在 C 語言中使用位移操作

本文將介紹幾種在 C 語言中使用位移操作的方法。

在 C 語言中使用 << 運算子將數字向左移位的方法

位移操作是每一種程式語言的一部分,它們將整數運算元的每個位重新定位到指定的位數。為了更好地展示這些操作的效果,我們在下面的例子中加入了名為 binary 的函式,它可以列印給定整數的二進位制表示。請注意,這個函式只實現了對 32 位整數值的操作。下面的示例程式碼演示了左移兩個位置並相應地顯示數字表示。

#include <stdio.h>
#include <stdlib.h>

void binary(unsigned n)
{
    unsigned i;
    for (i = 1 << 31; i > 0; i /= 2)
        (n & i) ? printf("1") : printf("0");
}

int main(int argc, char *argv[]) {
    int n1 = 123;

    binary(n1); printf(" : %d\n", n1);
    n1 <<= 2;
    binary(n1); printf(" : %d\n", n1);

    exit(EXIT_SUCCESS);
}

輸出:

00000000000000000000000001111011 : 123
00000000000000000000000111101100 : 492

在 C 語言中使用左移位來實現整數乘以二的計算

我們可以利用左移操作來實現乘二的計算,這樣可以提高硬體上的效率。需要注意的是,左移位時,算術移位和邏輯移位沒有區別。對於給定的整數,單位移位的結果是乘法,因此我們可以進一步移位,相應地得到乘法的結果。

#include <stdio.h>
#include <stdlib.h>

void binary(unsigned n)
{
    unsigned i;
    for (i = 1 << 31; i > 0; i /= 2)
        (n & i) ? printf("1") : printf("0");
}

int main(int argc, char *argv[]) {
    int n1 = 123;

    printf("%d\n", n1);
    n1 <<= 1;
    printf("%d x2\n", n1);

    exit(EXIT_SUCCESS);
}

輸出:

492
984 x2

C 語言中的右移-算術與邏輯移位的區別:

應該提到,有符號和無符號整數在下面的表示方式不同。也就是說,有符號的整數是作為二的補碼值來實現的。因此,負數最重要的位是 1,稱為符號位,而正數整數則照常以 0 開始。因此,當我們對負數進行邏輯右移時,就會失去其符號,得到正整數。所以,我們需要區分邏輯移位和算術移位,後者保留了最重要的位。即使概念之間有區別,C 語言也沒有提供單獨的運算子。此外,C 語言標準沒有規定標準行為,不同的硬體會有不同的實現。如下面的示例輸出所示,底層機器進行了算術轉移,並保留了整數的負值。

#include <stdio.h>
#include <stdlib.h>

void binary(unsigned n)
{
    unsigned i;
    for (i = 1 << 31; i > 0; i /= 2)
        (n & i) ? printf("1") : printf("0");
}

int main(int argc, char *argv[]) {
    int n2 = -24;

    binary(n2); printf(" : %d\n", n2);
    n2 >>= 3;
    binary(n2); printf(" : %d\n", n2);

    exit(EXIT_SUCCESS);
}

輸出:

11111111111111111111111111101000 : -24
11111111111111111111111111111101 : -3
Author: Jinku Hu
Jinku Hu avatar Jinku Hu avatar

Founder of DelftStack.com. Jinku has worked in the robotics and automotive industries for over 8 years. He sharpened his coding skills when he needed to do the automatic testing, data collection from remote servers and report creation from the endurance test. He is from an electrical/electronics engineering background but has expanded his interest to embedded electronics, embedded programming and front-/back-end programming.

LinkedIn