2013-07-15 30 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; 

你应该得到你所期望的结果。

相关问题