簡體   English   中英

位操作 - 指示有符號整數的符號

[英]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.

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