簡體   English   中英

為什么左移與變量產生不同的結果與常數?

[英]why does left shift with variables generate different result from that with constant?

在編譯下面的代碼后,我得到了一個奇怪的結果,a = 1而b = 0。 誰能解釋一下幕后發生的事情?

#include<iostream>
using namespace std;

int main(){

    int n=32; 
    int a=1<<n;  //turns out a=1
    int b=1<<32; //turns out b=0
    cout<<"a="<<a<<endl;
    cout<<"b="<<b<<endl;
}

因為您正在調用未定義的行為。 移位比該類型中存在的位更多的位未被定義為具有任何特定行為。

http://blog.llvm.org/2011/05/what-every-c-programmer-should-know.html?m=1

超大移位量:未定義將uint32_t移位32位或更多位。 我的猜測是,這是因為各種CPU上的基礎移位操作對此做了不同的事情:例如,X86將32位移位量截斷為5位(因此移位32位與移位0相同比特),但PowerPC將32位移位量截斷為6位(因此移位32會產生零)。 由於這些硬件差異,C的行為完全未定義(因此在PowerPC上移位32位可能會格式化您的硬盤,因此無法保證產生零)。 消除這種未定義行為的代價是編譯器必須為變量移位發出額外的操作(如'和'),這會使它們在普通CPU上的成本增加一倍。

標准沒有定義,或者更確切地說,它將其定義為“未定義的行為”,在左移超出整數類型大小的情況下會發生什么。 [這種未定義行為的原因是不同的硬件可能會或可能不會表現相同,例如,向左移動32位]。

在第一種情況下[至少沒有優化],編譯器生成指令來計算1 << 32 - 在x86上變成1 << (32 & 31) ,它與1 << 0相同 - 因此你得到1。

在第二種情況下,編譯器將計算值本身,該值變為溢出,並給出零。

很可能(但不確定)如果您更改編譯器選項以優化代碼,則兩種情況都會為零。 如果你要做一個較小班次的循環,你會得到你想要的行為(雖然你可能會發現“有趣”的行為,因為數字變為負數,所以最好使用unsigned進行所有的班次操作,真的) 。

暫無
暫無

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

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