2013-07-15 32 views
2
#include <stdio.h> 

int main(int argc, char const *argv[]) 
{ 
    char a = 0xAA; 
    int b; 

    b = (int)a; 
    b = b >> 4; 

    printf("%x\n", b); 
    return 0; 
} 

這裏的輸出是fffffffa。任何人都可以向我解釋這個輸出是如何獲得的?在字符中存儲十六進制數字

+3

可能是一個有符號的字符,這可能有助於'unsigned char a = 0xAA;' –

+1

請注意,沒有「十六進制數字」之類的東西。相反,你可能有一個「數字的十六進制表示」,就像你可能有相同數字的十進制或二進制表示一樣。一個數字是一個數字 - 它沒有基數。 –

+0

@HotLicks嘿......當然,你可以用「沒有數字這樣的東西」來追蹤它 - 「數字」只是人類想出的幫助邏輯思考事物的心理結構,如果確實存在像「邏輯」這樣的東西... ;-P – twalberg

回答

2

它看起來像0xAA得到符號擴展時,你把它放到一個int 0xFFFFFFAA。然後,當你將它右移四位(一個十六進制字符)時,你以0xFFFFFFFA結束。

//a is 8-bits wide. If you interpret this as a signed value, it's negative 
    char a=0xAA; 

    int b; //b is 32 bits wide here, also signed 

    //the compiler sign-extends A to 0xFFFFFFAA to keep the value negative 
    b=(int)a; 

    b=b>>4; //right-shift maintains the sign-bit, so now you have 0xFFFFFFFA 
3

C標準允許編譯器設計者選擇是否char帶符號。看起來你的系統使用簽署的char s和32位int s。由於0xAA(二進制10101010)的最高有效位已設置,因此該值會被符號擴展爲0xFFFFFFAA

移位有符號值也會對結果進行符號擴展,所以當您移出較低的四位時,四位從左邊移入,導致最終輸出0xFFFFFFFA

編輯:根據C99說明書中,十六進制整數常量如在你的例子0xAA被視爲取決於它們的長度int期不同的長度。因此,分配0xAA的簽署char超出範圍:將值的正確方法是用十六進制字符文字,像這樣:

char a='\xAA'; 
+0

你確定它沒有簽名溢出?:http://stackoverflow.com/questions/13569566/why-256-for-a-signed-char-is-undefined-in-c –

+2

@ShafikYaghmour我' m很確定右移不會導致溢出 - 這是一個符號擴展場景。然而,左移很容易造成溢出...... – twalberg

+1

那麼,如果它是一個有符號的char,那麼他會將一個超出範圍的值賦給'a',這是一個未定義的行爲。 –

1

該標準允許char以在任signedunsigned您它看起來像是signedsigned char指定0xAAsigned overflow,因此未定義的行爲。所以,如果你改變你的聲明如下:

unsigned char a=0xAA; 

你應該得到你所期望的結果。

相關問題