C++ 中的位移運算子

Anam Javed 2023年1月30日 2022年4月20日
  1. C++ 中的左位移位運算子
  2. C++ 中的右位移運算子
  3. C++ 中浮點資料型別的位移
  4. C++ 中陣列的位移
  5. C++ 中的位移位和掩碼
  6. C++ 中負數的位移
  7. 在 C++ 中使用 Long 進行位移
  8. まとめ
C++ 中的位移運算子

在 C++ 中,位移運算子按照其名稱的含義進行操作,即位移位。根據程式的要求,移位運算子將二進位制位向左或向右移動。

整數值應用於這些運算子(int、long、可能是 short 和 byte 或 char)。在某些語言中,對小於 int 的任何資料型別使用移位運算子會自動將運算元的大小調整為 int。

本文將詳細討論 C++ 中的左移和右移運算子及其實現以及相關示例。

C++ 中的左位移位運算子

左移運算子將移位表示式中的位向左移動加法表示式中的位數。移位操作騰出的位位置用零填充,從末尾移出的位被丟棄,包括符號位。

左移運算子需要兩個數字。這會移動第一個運算元的位,而第二個運算元決定要移位的位數。

你可以說將整數 a 與整數 b 左移,用 (a<<b) 表示,等效於將 a 乘以 2^b(2 的 b 次方)。左移運算子用 << 表示。

例如,M<<k。這裡,M 是第一個運算元,k 是第二個運算元。

讓我們取 M=33; 這是二進位制的 100001 和 k = 2。如果 M 左移 2,表示為 M=M<<2,它將變為 M=M(2^2)

因此,M=33(2^2)=132 可以寫成 10000100。

例子:

#include <iostream>
using namespace std;

int main()
{
    unsigned char x = 6, y = 7;
    cout <<"x<<1 = "<< (x<<1) << endl;
    cout <<"y<<1 = "<< (y<<1) << endl;
    return 0;
}

輸出:

x<<1 = 12
y<<1 = 14

在上面的程式碼中,unsigned char xchar y 變數表示一個字元資料型別,其中變數使用所有記憶體的 8 位,並且沒有符號位(在有符號的 char 中存在)。

這裡,char x 等於 6,即二進位制的 00000110,而 char y 等於 7,即二進位制的 00000111。

第一個 print 語句宣告將 x 的值左移 1 位;結果是 00001100。第二個列印語句將 y 的值左移 1 位;結果是 00001110。

C++ 中的右位移運算子

右移運算子將移位表示式中的位模式移動加法表示式向右提供的位數。對於無符號值,移位操作騰出的位位置是零填充的。

符號位替換有符號數中的空位位置。如果數字為正,則使用值 0;如果數字為負數,則使用值 1。

右移運算子需要兩個數字。這會移動第一個運算元的位,而第二個運算元決定要移位的位數。

你可以說將整數 a 與整數 b 右移,表示為 (a>>b),相當於將 a 除以 2^b(2 的 b 次方)。右移運算子表示為:>>

例如,M>>k 。這裡,M 是第一個運算元,k 是第二個運算元。

讓我們取 M=32; 這是二進位制的 100000 和 k = 2。如果 M 右移 2,表示為 M=M>>2,那麼 M 將變為 M=M/(2^2)。因此,M=32/(2^2)=8 可以寫成 1000。

示例程式:

#include <iostream>

int main()
{
    unsigned char x = 6, y = 9;
    cout <<"a>>1 = "<< (a >> 1)<< endl;
    cout <<"b>>1 = "<< (b >> 1) << endl;
    return 0;
}

輸出:

x>>1 = 3
y>>1 = 4

在上面的程式碼中,unsigned char xchar y 變數表示變數中的字元資料型別,它使用了記憶體的所有 8 位,並且沒有符號位(在有符號的 char 中存在)。

這裡,char x 等於 6,即二進位制的 00000110,而 char y 等於 9,即二進位制的 00001001。

第一個 print 語句宣告將 x 的值右移 1 位;結果是 00000011。第二個列印語句宣告將 y 的值右移 1 位;結果是 00000100。

C++ 中浮點資料型別的位移

你不能在 C++ 中對浮點數進行位移,因為它會顯示錯誤,但這是為什麼呢?這是因為浮點數以特殊格式儲存。

浮點數的 32 位分為兩類:有效數和指數。移位可能會將位從指數類別轉移到有效數字類別,反之亦然。

例子:

#include <stdio.h>

int main( int ar, char *arg[] )
{
    float testFl = 2.5;

    printf( "testFloat (before): %f\n", testFl );
    testFl = testFl << 1;
    printf( "testFloat (after): %f\n", testFl );
    return 0;
}

輸出:

error: invalid operands to binary << (have 'float' and 'int')

右移或左移將摺疊所有位。

C++ 中陣列的位移

有一個大小為 n 的陣列 ar[] 和一個整數 m

目標是通過對存在的所有陣列元素執行右移操作來使所有陣列元素 > m。如果你不能這樣做,請列印 -1。

例子:

Input: ar[] = { 21, 22, 23, 19 }, m = 34
Output: { 26, 26, 27, 25 }

Explanation:
ar[0] = 10101
After 1 right shift, 11010 → 26
ar[1] = 10110
After 3 right shift, 11010 → 26
ar[2] = 10111
After  1 right shift, 11011 → 27
ar[3] = 10011
After 2 right shift, 11001 → 25

程式碼:

#include <bits/stdc++.h>
using namespace std;

int setBitNumber(int n)
{
    int m = log2(n);
    return m;
}

bool check(int ar[], int m, int n)
{
    for (int i = 0; i < n; i++) {
        if (ar[i] <= m)
            return false;
}
return true;
}

void modifyArray(int ar[], int m, int n)
{
for (int i = 0; i < n; i++) {
    if (ar[i] > m)
        continue;
    else {
       int bits = setBitNumber(ar[i]);
        int el = ar[i];
        for (int j = 0; j < bits; j++) {
            if (el & 1) {
                el >>= 1;
                el |= (1 << bits);
            }
            else {
                el >>= 1;
            }
            if (el > m) {
                arr[i] = el;
                break;
            }
        }
    }
}

if (check(ar, m, n)) {
    for (int i = 0; i < n; i++)
        cout << ar[i] << " ";
}
else
    cout << -1;
}

int main()
{
    int ar[] = { 21, 22, 23, 19 };
    int n = sizeof(ar) / sizeof(ar[0]);
    int m = 24;
    modifyArray(ar, m, n);
    return 0;
}

輸出:

[26, 26, 27, 25]

程式中執行的主要操作是陣列的遍歷。它對陣列 ar[i] 的每個元素進行右移操作。

如果 ar[i] > m,則檢查條件。如果為真,則更新陣列 ar[i],否則繼續。

如果陣列 ar[i] ≤ m 的任何元素,則列印-1,否則列印陣列 ar[i]

C++ 中的位移位和掩碼

掩碼指定應保留哪些位以及應清除哪些位。

例子:

Mask:   00001111b
Value:  01010101b

當我們對值應用掩碼時,我們希望清除前(高)四位,同時保留最後(低)四位。結果,我們檢索到了底部的四位。

輸出:

Mask:   00001111b
Value:  01010101b
Result: 00000101b

位移運算子經常與掩碼操作一起使用,以將位從一個數字中逐一剝離。以下示例說明了如何將 unsigned char 劃分為單獨的位陣列。

unsigned char y = 0xD5;
unsigned char bit[8];
unsigned char mask = 1;
for(int x = 7;x >= 0;x--) {
    bits[x] = y & mask;
    y = y >> 1;
}

C++ 中負數的位移

不應使用左右移位運算子輸入負數。如果任一運算元是負整數,則結果是未定義的行為。

例如,1 >> -11 << -1 的結果都是未定義的。

#include <iostream>

int main()
{
    unsigned char x = -6,
    cout <<"a>>1 = "<< (a >> 1)<< endl;
    return 0;
}

輸出:

error: undefined behavior in C

在 C++ 中使用 Long 進行位移

資料型別 long 用於位移 32 位或 64 位。

例子:

對於 32 位,

unsigned long A = (1L << 37)

對於 64 位,

unsigned long long A = (1ULL << 37);

使用程式實現以下內容:

#include <stdio.h>

int main(void)
{
    long long y = 1ULL;

    // Left shift 40 times
    y <<= 20;
    y <<= 20;

    printf("y is %lld\n", y);
    return 0;
}

輸出:

y is 1099511627776

這裡,取一個 64 位變數 long long y,而 1ULL 是一個無符號 long long int 常量(64 位)。變數 y 移動 40 次並列印出來。

まとめ

在本文中,我們討論了 C++ 中的位移位運算子。我們詳細瞭解了 C++ 中的左右移位運算子。

相關文章 - C++ Operator