[英]Bitwise shift operation in C on uint64_t variable
我有以下示例代碼:
uint64_t x, y;
x = ~(0xF<<24);
y = ~(0xFF<<24);
結果將是:
x=0xfffffffff0ffffff
y=0xfffff
有人可以解釋這個區別嗎? 為什么x計算超過64位而y只計算在32位?
默認操作是32位。
x=~(0xf<<24);
此代碼可以反匯編為以下步驟:
int32_t a;
a=0x0000000f;
a<<=24; // a=0x0f000000;
a=~a; // a=0xf0ffffff;
x=(uint64_t)a; // x = 0xfffffffff0ffffff;
和,
y = ~(0xFF<<24);
int32_t a;
a=0x000000ff;
a<<=24; // a=0xff000000;
a=~a; // a=0x00ffffff;
x=(uint64_t)a; // x = 0x000000000ffffff;
因為0x0f << 24
在被視為int
時是正數,所以它被符號擴展為正數,即到0x00000000_0f000000
(下划線只是為了可讀性,C不支持這種語法)。 然后將其轉換為您所看到的內容。
另一方面, 0xff << 24
是負數,因此它的符號擴展方式不同。
其他海報已經說明了為什么會這樣做。 但要獲得預期的結果:
uint64_t x, y;
x = ~(0xFULL<<24);
y = ~(0xFFULL<<24);
或者你可以這樣做(我不知道這是否比上面的慢):
uint64_t x, y;
x = ~(uint64_t(0xF)<<24);
y = ~(uint64_t(0xFF)<<24);
然后:
x = 0xfffffffff0ffffff
y = 0xffffffff00ffffff
您的程序中有未定義的行為,因此可能發生任何事情。
int
,相當於signed int
。 在這個特定的平台上, int
顯然是32位。 int
。 int
因此不會發生隱式類型的提升。 因此<<操作的結果也是(簽名的) int
。 int
,因此一切正常。 int
! 在這里,調用未定義的行為,並且可能發生任何事情。 ISO 9899:2011 6.5.7 / 4:
“E1 << E2的結果是E1左移E2位位置;空位用零填充。” / - /
“如果E1具有帶符號類型和非負值,並且E1×2E2在結果類型中可表示,那么這就是結果值;否則,行為是未定義的。
因此不能使用表達式0xFF << 24。 該程序可以隨后打印任何垃圾值。
但如果我們忽略那一個並專注於0x0F <24:
int
。 〜運算符適用於此。 像這樣的錯誤是為什么編碼標准MISRA-C包含許多規則來禁止在這樣的表達式中使用整數文字。 符合MISRA-C的代碼必須在每個整數文字后使用u
后綴(MISRA-C:2004 10.6),並且不允許代碼對有符號整數執行按位運算(MISRA-C:2004 12.7)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.