[英]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位,因此bit32R
和bit32L
的初始化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.