在C语言中使用casting的一种奇怪现象

在C语言中使用casting的一种奇怪现象,c,C,以下代码: int main() { int small_num = 0x12345678; int largest_num = 0xFFFFFFFF; printf("small: without casting to short: 0x%.8x, with casting to short: 0x%.8x\n", small_num>>16, (short)(small_num>>16)); printf("large: witho

以下代码:

int main() {
    int small_num   = 0x12345678;
    int largest_num = 0xFFFFFFFF;
    printf("small: without casting to short: 0x%.8x, with casting to short: 0x%.8x\n", small_num>>16, (short)(small_num>>16));
    printf("large: without casting to short: 0x%.8x, with casting to short: 0x%.8x\n", largest_num>>16, (short)(largest_num>>16));
    return 0;
}
给我输出(使用):

这似乎非常奇怪。有人知道为什么会这样吗?

当您在printf调用中转换为(short)时,编译器会将它从short转换回int,int是传递给printf的参数。因此,1234将映射到1234,而ffff(正好是-1)映射到FFFFFF。请注意,通过在负整数的左边添加“on bits”,负整数可以从短扩展到长。

short-response 十六进制常量的类型为
无符号int
。当转换为有符号整数时,该值变为
-1
。右移负值通常会使符号位保持不变,因此
-1>>16
仍然是
-1
。传递给变量函数的
short int
被提升为
signed int
,当
%x
转换说明符将其解释为
无符号int
时,会打印出
0xffffffff

长话短说 但是,您的代码被破坏的原因有很多

整数转换
int最大值\u num=0xFFFFFFFF

十六进制常量的类型是以下类型中可以表示其值的第一种:
int
无符号int
长int
无符号长int
无符号长int
无符号长int

如果
int
的长度超过32位,就可以了。 如果
int
具有32位或更少,则结果为实现定义的(或引发实现定义的信号

通常,
最大\u num
将设置所有位,并具有值
-1

转移负值
最大数量>>16

如果
最大值
为负值,则结果值为实现定义的值。通常,符号位保持不变,因此
-1
右移仍然
-1

整数升级
printf(“0x%.8x\n”(短)(最大数量>>16))

short int
传递给变量函数时,该值将提升为
int
。转换为新类型时将保留负值

但是,
“%x”
转换说明符需要一个
无符号int
参数。由于
无符号整数
有符号整数
是不兼容的类型,因此代码的行为未定义的。通常,
signed int
的位被重新解释为
unsigned int
,这导致十六进制常量的原始值

调用变量函数
printf(…)

printf()
是一个可变函数。可变函数(通常)使用与普通函数不同的调用约定。如果在作用域中没有有效的
print()
声明,代码将调用未定义的行为

printf()
提供声明的常用方法是
包括



来源:(当前C标准的最后一份公开草案)。

移位操作将保留
int
的符号,符号存储在
int
的最高有效位。如果您期望0x0000FFFF,也可能重复,移位后结果为0xFFFF。
small: without casting to short: 0x00001234, with casting to short: 0x00001234
large: without casting to short: 0xffffffff, with casting to short: 0xffffffff