優化時,GCC有時告訴我爲什麼在將分區更改爲右移時可能會發生符號溢出?
假設符號溢出簡化
/
或%
到>>
或&
時
[-Wstrict-overflow
]
我沒有做一個可重複的測試情況下不會出現爲此,但我的生產代碼包含類似於
int left = a.left() + (a.width() - b.width())/2;
其中所有方法返回值爲int
。
爲什麼編譯器將/2
替換爲>>1
或者(例如)%4
與&3
會導致整數溢出?
優化時,GCC有時告訴我爲什麼在將分區更改爲右移時可能會發生符號溢出?
假設符號溢出簡化
/
或%
到>>
或&
時
[-Wstrict-overflow
]
我沒有做一個可重複的測試情況下不會出現爲此,但我的生產代碼包含類似於
int left = a.left() + (a.width() - b.width())/2;
其中所有方法返回值爲int
。
爲什麼編譯器將/2
替換爲>>1
或者(例如)%4
與&3
會導致整數溢出?
將新位移入符號位會導致意外的結果發生: 1001(帶符號的十進制:7)>> 1結果爲: 0100(帶符號的十進制:4)。 至少在使用二進制補碼的實現中,這是大多數。
編輯:但是,在x86上,有移位指令保留符號位。
我上次檢查時,二進制1001是十進制9,9/2 == 4。鑑於編譯器知道參數是(帶符號)整數,我期望它能夠(a)使用(或模擬)帶符號的右移,或者(b)如果它知道它是不合理的,就跳過這種簡化。 –
>>有符號整數取決於實現。請參閱:http://stackoverflow.com/questions/11644362/are-the-results-of-bitwise-operations-on-signed-integers-defined – virgesmith
我想我誤解了警告意味着結果可能是** undefined **。但它只是告訴我們它是**實現定義的**。這並不是很糟糕 - 但仍然值得警告。 –
請注意,這與用'>>'替換'/'的程序員*不同,因爲編譯器應該知道它的目標是什麼。 –