#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