#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
。任何人都可以向我解釋這個輸出是如何獲得的?在字符中存儲十六進制數字
#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
。任何人都可以向我解釋這個輸出是如何獲得的?在字符中存儲十六進制數字
它看起來像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
C標準允許編譯器設計者選擇是否char
帶符號。看起來你的系統使用簽署的char
s和32位int
s。由於0xAA
(二進制10101010
)的最高有效位已設置,因此該值會被符號擴展爲0xFFFFFFAA
。
移位有符號值也會對結果進行符號擴展,所以當您移出較低的四位時,四位從左邊移入,導致最終輸出0xFFFFFFFA
。
編輯:根據C99說明書中,十六進制整數常量如在你的例子0xAA
被視爲取決於它們的長度int
期不同的長度。因此,分配0xAA
的簽署char
超出範圍:將值的正確方法是用十六進制字符文字,像這樣:
char a='\xAA';
你確定它沒有簽名溢出?:http://stackoverflow.com/questions/13569566/why-256-for-a-signed-char-is-undefined-in-c –
@ShafikYaghmour我' m很確定右移不會導致溢出 - 這是一個符號擴展場景。然而,左移很容易造成溢出...... – twalberg
那麼,如果它是一個有符號的char,那麼他會將一個超出範圍的值賦給'a',這是一個未定義的行爲。 –
該標準允許char
以在任signed
或unsigned
您它看起來像是signed
。 signed char
指定0xAA
爲signed overflow,因此未定義的行爲。所以,如果你改變你的聲明如下:
unsigned char a=0xAA;
你應該得到你所期望的結果。
可能是一個有符號的字符,這可能有助於'unsigned char a = 0xAA;' –
請注意,沒有「十六進制數字」之類的東西。相反,你可能有一個「數字的十六進制表示」,就像你可能有相同數字的十進制或二進制表示一樣。一個數字是一個數字 - 它沒有基數。 –
@HotLicks嘿......當然,你可以用「沒有數字這樣的東西」來追蹤它 - 「數字」只是人類想出的幫助邏輯思考事物的心理結構,如果確實存在像「邏輯」這樣的東西... ;-P – twalberg