2017-08-26 45 views
2

我有以下代碼段,C++ - 右移位不正確地評價內部IF

if (index > ((v.size() >> 1) - 1)) { } 

v.size()是0,並且索引是1。執行不會進入如果塊。但是,如果我改變上面的代碼,

int limit = (v.size() >> 1) - 1; 
if (index > limit) { } 

並用v.size()和索引的相同的值時,執行不進入如果塊。

爲什麼會發生這種行爲?謝謝。

+3

可能是因爲'v.size()'不是'int'。但是我們不知道它的作用,因爲代碼中缺少相關的上下文。 – melpomene

+1

啊,忽略警告...... –

+0

這是由於隱式轉換爲無符號類型。第二種方法是有效的演員。很好的問題:我不明白downvote。 – Bathsheba

回答

0

你顯然正在執行無符號比較。返回類型v.size()可能是size_t,它是一個無符號整數。因此,表達式(v.size() >> 1) - 1產生最大可能的無符號整數。除非您將其轉換回有符號整數類型,否則您將無法獲得正面的比較結果。

一個簡單的強制轉換爲ssize_t減法之前,將解決你的問題:

if (index > (((ssize_t)v.size() >> 1) - 1)) { } 

我用ssize_t,因爲該類型保證能容納任何size_t價值,如果它重新詮釋爲負面其最重要的位被設置。這不能說是int,因爲通常在64位平臺上只有32位。因此,像你在第二個例子中那樣使用int,可能會切斷一些位。

+0

我不能相信人們仍然會犯這種錯誤,你必須在扣除之前將其轉換爲簽名類型*!在*無符號溢出(這很好並且定義好)之後投射*太遲了,您會得到簽名溢出,這是未定義的行爲(包裹*不*保證,並且編譯器即使在補碼環繞將會是平臺的情況下也會利用這個未定義的行爲自然)。只需將'size()'的結果轉換爲有符號類型並對其執行算術運算。 –

+0

@MatteoItalia Afaik,'(int)(unsigned)i == i'由新標準定義。您能否爲您的索賠提供標準參考? – cmaster

+0

即使它是(標準引用?),它不是我們的情況 - 你沒有執行從/到經過無符號值的有符號值的往返,你計算的是一個無符號值溢出,然後將其轉換爲有符號值。這不能保證產生任何有用的東西(例如,它明顯無法在具有例如符號和數量級或補碼錶示的整數平臺上正常工作)。 –