鉴于,
unsigned short y = 0xFFFF;
我打印时
printf("%x", y);
我得到:0xFFFF;
但是当我打印
时printf("%x", (signed short)y);
我得到:0xFFFFFFFF
以下整个计划:
#include <stdio.h>
int main() {
unsigned short y = 0xFFFF;
unsigned short z = 0x7FFF;
printf("%x %x\n", y,z);
printf("%x %x", (signed short)y, (signed short)z);
return 0;
}
当我们将较低字节数据类型转换为较高字节数据类型时,会发生符号扩展,但是这里我们将签名简短的类型缩短。 在两种情况下,sizeof((有符号短)y)或sizeof((有符号短)z)打印2个字节。如果符号位为0,则为0x7fff的短字节,为2个字节。 非常感谢任何帮助!
答案 0 :(得分:5)
第一个printf
的输出符合预期。第二个printf
产生未定义的行为。
在C语言中,当您传递小于int
的值作为可变参数时,该值始终隐式转换为类型int
。物理传递short
或char
可变参数不可能。隐式转换为int
是您的&#34;签署扩展名&#34;发生了。
因此,您的printf("%x", y);
相当于printf("%x", (int) y);
。传递给printf
的值为0xFFFF
类型的int
。从技术上讲,%x
格式需要unsigned int
参数,但非负int
值也可以(除非我缺少一些技术性)。输出为0xFFFF
。
在第二种情况下也会转换为int
。即您的printf("%x", (signed short) y);
相当于printf("%x", (int) (signed short) y);
。 0xFFFF
到(signed short)
的转换是由实现定义的,因为0xFFFF
显然超出了您平台上signed short
的范围。但最有可能产生负值(-1
)。转换为int
时,它会生成类型int
的相同负值(同样,-1
表示为0xFFFFFFFF
,用于32位int
。进一步的行为是未定义的,因为您要为格式说明符int
传递负%x
值,这需要unsigned int
参数。使用%x
为int
值为printf
是违法的。
换句话说,正式你的第二个0xFFFFFFFF
打印出不可预测的垃圾。但实际上上面解释了{{1}}的来源。
答案 1 :(得分:1)
让我们把它分解成小块:
鉴于,
unsigned short y = 0xFFFF;
假设最大值为unsigned short
的{{1}}为2^16-1
,那确实是0xFFFF
。
我打印时
printf("%x", y);
由于默认参数提升(因为printf()
是可变函数),y
的值被隐式提升为类型int
。如果指定了%x
格式,则将其视为unsigned int
。假设公共双补码表示和四字节int
类型,这意味着当最高有效位设置为零时,int
和unsigned int
的位模式完全相同。
但是当我打印
时
printf("%x", (signed short)y);
您所做的是转换为签名类型,不能代表0xFFFF
的值。标准停留的这种转换是实现定义的,因此您可以得到任何结果。在隐式转换为int
之后,您显然拥有32位的位图,表示为0xFFFFFFFF
。