我将在几个小时内参加C决赛,我正在考试过去,试图确保我理解以前错过的问题。我有以下问题,我只是把它留空,因为我不知道答案,我继续前进,现在看着它我不知道答案是什么......问题是;
signed short int c = 0xff00;
unsigned short int d, e;
c = c + '\xff';
d = c;
e = d >> 2;
printf("%4x, %4x, %4x\n",c,d,e);
我们被要求显示要打印的值?这是'xff'的加法让我失望。我已经解决了二进制中的类似问题,但这种十六进制表示让我感到困惑。
有人能告诉我这里会发生什么吗?
答案 0 :(得分:2)
'\xff'
相当于二进制中的所有1
或-1
中的signed int
。
最初是c = 0xff00
c = c + '\xff'
二进制是
c = 1111 1111 0000 0000 + 1111 1111 1111 1111
产生signed short int
c = 1111 1110 1111 1111 (0xfeff)
c
和d
因分配而相同,但e
右移两次
e = 0011 1111 1011 1111 (0x3fbf)
我冒昧地试试这个。在代码中,我添加了short int f
,其值为c - 1
。
unsigned short int c = 0xff00, f;
unsigned short int d, e;
f = c-1;
c = c + '\xff';
d = c;
e = (d >> 2);
printf("%4x, %4x, %4x, %4x\n",c,d,e,f);
我对c
和f
都得到了相同的结果。 f = c - 1
不是缓冲区溢出。 <{1}}也不是缓冲区溢出
c + '\xff'
正如Zan Lynx所述,我在示例代码中使用了feff, feff, 3fbf, feff
,但原始帖子是unsigned short int
。使用signed int,输出将有4个额外的f。
答案 1 :(得分:1)
0xff00
表示二进制字符串1111 1111 0000 0000
。
'\xff'
是一个数字代码为0xff
的字符,因此只是1111 1111
。
答案 2 :(得分:1)
signed short int c = 0xff00;
正在初始化c
超出范围值(0xff00 = 65280 in decimal)
。这将导致产生错误结果。
答案 3 :(得分:1)
第一次添加会添加存储在c
中的16位数字:
1111 1111 0000 0000
加上编码为''之间的ASCII字符值的数字。但在C中,您可以将字符指定为前缀为\x
的十六进制代码,如'\xNN'
,其中NN
是一个两位十六进制数字。该字符的ASCII码是NN
本身的值。因此,'\xFF'
0xFF
是一种不同寻常的方式。{/ 1}。
使用signed short
(16位,有符号)加char
(8位,有符号)执行加法。为此,编译器将该8位值提升为16位值,通过进行符号扩展转换来保留原始符号。
因此,在添加之前,'xFF'
被解码为8位有符号数0xFF
(1111 1111)
,而后者又被提升为16位数1111 1111 1111 1111
(必须保留标志)
最后的补充是
1111 1111 0000 0000
1111 1111 1111 1111
-------------------
1111 1110 1111 1111
哪个是十六进制数0xFEFF
。这是变量c
中的新值。
然后,d=c;
d
为unsigned short
:它的大小与signed short
相同,但此处不考虑符号; MSb只是另一个点。由于两个变量的大小相同,d
中的值与c
中的值完全相同。那就是:
d = 1111 1110 1111 1111
不同之处在于,使用此编号的任何aritmetic或逻辑操作都不会考虑在内。这意味着,例如,改变数字大小的转换不会扩展符号。
e = d >> 2;
e
将d
的值向右移两位。 >>
运算符的行为有所不同,具体取决于左操作数是否已签名。如果它是有符号的,则执行移位以保留符号(从左边输入数字的位将具有与移位前数字所具有的原始符号相同的值)。如果不是,则从左侧进入零。
d
是无符号的,因此值e
得到的结果是将d
两位向右移,从左边输入零:
e = 0011 1111 1011 1111
哪个是0x3FBF
。
最后,打印的值为c,d,e
:
0xFEFF, 0xFEFF, 0x3FBF
但您可能会看到0xFFFFFEFF
作为第一个打印的号码。这是因为%x
需要int
,而不是short
。 4
中的"%4x"
表示:“使用至少4位数来打印数字,但如果需要的位数更多,请根据需要使用”。要将0xFEFF
打印为int
(实际为32位整数),必须再次升级,并且在签名时,这是通过符号扩展完成的。因此0xFEFF
变为0xFFFFFEFF
,需要打印8位数字,因此确实如此。
第二个和第三个%4x
打印无符号值(d
和e
)。这些值被提升为32位整数,但这次是无符号的。因此,第二个值提升为0x0000FEFF
,第三个值提升为0x00003FBF
。这两个数字实际上不需要打印8个数字,而是4个,所以它会这样做而且每个数字只能看到4个数字(尝试将%4x
改为最后%2x
个{{1}}看到这些数字仍然印有4位数字)