C语言中的类型转换查询

C语言中的类型转换查询,c,gcc,types,C,Gcc,Types,为什么下面的代码将值打印为-25536而不是-25535。我的猜测是,要使短范围内的短值正常化,它应该做40000-32767=7233,然后从第一个范围开始,即-32768+7233=-25535,那么额外的值从何而来?为什么是-25536 #include <stdio.h> int main() { short int a = 40000; printf("%d", a); return 0; } #包括 int main() {

为什么下面的代码将值打印为-25536而不是-25535。我的猜测是,要使短范围内的短值正常化,它应该做40000-32767=7233,然后从第一个范围开始,即-32768+7233=-25535,那么额外的值从何而来?为什么是-25536

#include <stdio.h>
int main()
{
    short  int a = 40000;
    printf("%d", a);
    return 0;
}
#包括
int main()
{
短整数a=40000;
printf(“%d”,a);
返回0;
}

在C 2018标准中,6.3.1.3 3表示,将无法在类型中表示的值转换为有符号整数类型是实现定义的,其中N是类型的宽度(类型中的位数,包括符号位)

在您使用的C实现中,
short int
有16位,因此转换换位模216=65536。所以40000被转换成
short int
,减去65536的次数可以得到一个范围内的值(−32768到+32767),这仅仅是一次:40000−65,536 = −25536


注意,纯二进制中40000的位是1001100 0100 0000(215+212+211+210+26=32768+4096,+2048+1024+64=40000)。当解释为2的补码时,前导位表示−32768而不是+32768,因此两个补码中相同位的解释是−32,768 + 4,096, + 2,048 + 1,024 + 64 = −25,536. 这以及二的补码和二进制的算术性质与GCC选择包装模2N的原因有关。

首先,正确的代码是

printf(“%hd”,a);
如果您启用了编译器的警告,那么编译器会警告您这个问题
gcc
甚至给出了解决方案


获得-25536并不能保证。但事情是这样的

在具有32位
int
vars的little-endian 2的补码机器上,
40000
存储为字节
409c00

在具有16位
short
vars的小endian 2 s-complete机器上,字节
409c
表示-25536

不执行任何操作



你的问题的关键是。您应该会发现最相关的。

要执行的操作是65536-40000=-25536C11标准草案n1570:6.3转换6.3.1.1布尔、字符和整数6.3.1.3有符号和无符号整数[…]3否则,新类型是有符号的,并且不能在其中表示值;要么结果是实现定义的,要么发出实现定义的信号。@mouviciel那么在
短无符号int a=70000
的情况下执行什么操作,因为这样a将被打印为4464。它是不是
65536-70000
=-4464,然后是0-(-4464)?`@SakshiTanwar:转换为模65536,这意味着需要增加或减少65536的次数才能使值进入范围。所以70000是通过减去65536一次来转换的:70000−65536=4464。这相当于:while(a>32768)a-=65536;当(a<-32767)a+=65536;时,大底片也是如此。这并不意味着代码就是这么做的。代码只是将40000位放入2字节(shirt int),然后编译器将这些位作为-32767和32678之间的有符号值打印出来。