[英]Bit Operations - Indicating the Sign of a Signed Integer
為什么以下C代碼不能用於返回-1表示負數,0表示0表示,1表示正數表示?
(((x >> 31) ^ -1) + 1) | (!x ^ 1);
具體來說,當我傳入負數時,它返回1.雖然看起來我有一個負數(即31位移位后最低有效位為1),但是將它與-1進行異或會給我-2(即,最低有效位中的所有1和0),加1將使其為-1。
>>
通常會對簽名數據進行算術移位,因此((-1) >> 31) == (-1)
,與您的假設相反。 正如其他人所指出的那樣,標准並不能保證這一點,但在現代系統中很可能是這樣。 在任何情況下,要小心這種類型的鑽頭。 如果可移植性是一個問題或速度不是,你應該以不同的方式。 請參閱C / C ++中是否有標准符號函數(signum,sgn)? 一些想法。
根據C99標准,如果x為負,則x >> n
的結果是實現定義的。 所以你遇到問題的原因取決於你的編譯器和架構。
但是,當你移動它時,x很可能是符號擴展,即重復頂部位以保持符號與操作數相同。 這是我的編譯器發生的事情。 因此,對於任何負數, x >> 31
為-1
。 此外,對於任何非零數字!x
為0(即假)。 這適用於假設x是32位整數。 如果使x成為unsigned int,它應該可以工作,但請考慮以下替代方法:
(x < 0) ? -1 : ((x > 0) ? 1 : 0)
我認為這有點不那么神秘了。
這是一個程序,您可以使用它來查看您的表達式正在做什么
#include <stdio.h>
#define EVALUATE(x) printf("%s = %d\n", #x, x)
int main(int argc, char** argv)
{
unsigned int x = 51;
EVALUATE(x >> 31);
EVALUATE(((x >> 31) ^ -1));
EVALUATE(((x >> 31) ^ -1) + 1);
EVALUATE(!x);
EVALUATE(!x ^ 1);
EVALUATE((((x >> 31) ^ -1) + 1) | (!x ^ 1));
return 0;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.