簡體   English   中英

C中的右左移位位

[英]right left shift bits in C

我對C中的位移位進行了一次小測試,所有移位0、8、16位都可以,並且我知道發生了什么。

但是對我來說尚不清楚32位左右移位,我正在測試的變量是32位長。

然后,我更改了將保留移位結果的32位變量,但是32位右移是相同的!

這是我的代碼:

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

int main() {
    uint32_t code = 0xCDBAFFEE;

    uint64_t bit32R = code >> 32;
    uint16_t bit16R = code >> 16;
    uint8_t bit8R = code >> 8;
    uint8_t bit0R = code >> 0;

    uint64_t bit32L = code << 32;
    uint16_t bit16L = code << 16;
    uint8_t bit8L = code << 8;
    uint8_t bit0L = code << 0;

    printf("Right shift:\nbit32R %.16x\nbit16R %x\nbit8R %x\nbit0R %x\n\n",
           bit32R, bit16R, bit8R, bit0R);
    printf("Left shift:\nbit32L %.16x\nbit16L %x\nbit8L %x\nbit0L %x\n\n",
           bit32L, bit16L, bit8L, bit0L);
}

這是我得到的結果:

Right shift:
bit32R 00000000cdbaffee
bit16R 0
bit8R cdba
bit0R ff

Left shift:
bit32L 00000000cdbaffee
bit16L 0
bit8L 0
bit0L 0

Process returned 61 (0x3D)   execution time : 0.041 s
Press any key to continue.

將整數右移等於或大於其大小的位數是未定義的行為。

C11 6.5.7按位移位運算符

句法

 shift-expression: additive-expression shift-expression << additive-expression shift-expression >> additive-expression 

約束條件

每個操作數應具有整數類型。

語義學

對每個操作數執行整數提升。 結果的類型是提升后的左操作數的類型。 如果右操作數的值為負或大於或等於提升的左操作數的寬度,則行為是不確定的。

E1 << E2的結果是E1左移E2位位置; 空位用零填充。 如果E1具有無符號類型,則結果的值為E1 ×2 E2 ,比結果類型中可表示的最大值模減少一個。 如果E1具有帶符號的類型和非負值,並且E1 ×2 E2在結果類型中可表示,則這是結果值; 否則,行為是不確定的。

E1 >> E2的結果是E1右移E2位位置。 如果E1具有無符號類型或E1具有符號類型和非負值,則結果的值是E1 / 2 E2商的整數部分。 如果E1具有帶符號的類型和負值,則結果值是實現定義的。

您平台上int的大小似乎最多為32位,因此bit32Rbit32L的初始化bit32L具有未定義的行為。

64位表達式應編寫為:

uint64_t bit32R = (uint64_t)code >> 32;

uint64_t bit32L = (uint64_t)code << 32;

此外, printf中使用的格式對於傳遞的參數而言是不正確的(除非int具有64位,這將產生不同的輸出)。

您的編譯器似乎不完全符合C99,您應該添加最終return 0;否則, return 0; 函數main()末尾的語句。

這是更正的版本:

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

int main(void) {
    uint32_t code = 0xCDBAFFEE;

    uint64_t bit32R = (uint64_t)code >> 32;
    uint16_t bit16R = code >> 16;
    uint8_t bit8R = code >> 8;
    uint8_t bit0R = code >> 0;

    uint64_t bit32L = (uint64_t)code << 32;
    uint16_t bit16L = code << 16;
    uint8_t bit8L = code << 8;
    uint8_t bit0L = code << 0;

    printf("Right shift:\n"
           "bit32R %.16"PRIx64"\n"
           "bit16R %"PRIx16"\n"
           "bit8R %"PRIx8"\n"
           "bit0R %"PRIx8"\n\n",
           bit32R, bit16R, bit8R, bit0R);

    printf("Left shift:\n"
           "bit32L %.16"PRIx64"\n"
           "bit16L %"PRIx16"\n"
           "bit8L %"PRIx8"\n"
           "bit0L %"PRIx8"\n\n",
           bit32L, bit16L, bit8L, bit0L);

    return 0;
}

輸出為:

Right shift:
bit32R 0000000000000000
bit16R cdba
bit8R ff
bit0R ee

Left shift:
bit32L cdbaffee00000000
bit16L 0
bit8L 0
bit0L ee

這可能不是您所期望的,因為變量的類型有些不一致。

一個問題是您正在使用%x打印64位整數。 您應該為每個變量使用正確的格式說明符。 有可用的宏:

#define __STDC_FORMAT_MACROS
#include <inttypes.h>

// ...

printf("64 bit result: %" PRIx64 "\n", bit32R);
printf("16 bit result: %" PRIx16 "\n", bit16R);
printf("8 bit result: %" PRIx8 "\n", bit8R);

可以在此處找到更多信息。

您沒有在此處執行64位左移,因為代碼是uint32_t,所以編譯器使用32位版本的operator。 另外,您應該告訴print使用long long(與uint64_t相同)

#include <cstdint>
#include <stdio.h>
int main ()
{
uint32_t code = 0xCDBAFFEE;


uint64_t bit32R=((uint64_t)code)>>32;
uint16_t bit16R=code>>16;
uint8_t bit8R=code>>8;
uint8_t bit0R=code>>0;

uint64_t bit32L=((uint64_t)code)<<32;
uint16_t bit16L=code<<16;
uint8_t bit8L=code<<8;
uint8_t bit0L=code<<0;


printf("Right shift:\nbit32R %llx\nbit16R %x\nbit8R %x\nbit0R %x\n\n", bit32R,bit16R,bit8R,bit0R);
printf("Leftt shift:\nbit32L %llx\nbit16L %x\nbit8L %x\nbit0L %x", bit32L,bit16L,bit8L,bit0L);
}

結果是:

Right shift:
bit32R 0
bit16R cdba
bit8R ff
bit0R ee

Leftt shift:
bit32L cdbaffee00000000
bit16L 0
bit8L 0
bit0L ee

如果您具有C99兼容的編譯器,則應使用inttypes.h中定義的宏,可悲的是某些平台沒有這些定義。 printf的格式描述符與平台有關。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM