解释类型转换如何在 C 中从 int 到 short 的位级别工作
Posted
技术标签:
【中文标题】解释类型转换如何在 C 中从 int 到 short 的位级别工作【英文标题】:Explain how typecasting works at the bit level from int to short in C 【发布时间】:2013-09-11 08:39:58 【问题描述】:如果 2^31-1 的二进制表示为 01111111 11111111 11111111 11111111,那么当类型转换为 short 时,该二进制数会发生什么情况?这是假设一个 int 是 4 个字节,而一个 short 是 2 个字节。
我写了一个测试程序,当 typecast to short 时输出为 -1。它是否正确?这是否意味着 typecast to short 只是砍掉了 16 个最高有效位,留下 11111111 11111111(有符号 2 的补码)?
代码
#include <stdio.h>
#include <stdlib.h>
void main()
int x = sizeof(int);
int y = sizeof(short);
printf("%d, %d",x,y);
int a = 2147483647;
short b = (short)a;
printf("\nad: %d",(int)a);
printf("\nax: %x",(int)a);
printf("\nau: %u",(int)a);
printf("\nbd: %d",(int)b);
printf("\nbx: %x",(int)b);
printf("\nbu: %u",(int)b);
printf("\n");
输出
4, 2
ad: 2147483647
ax: 7fffffff
au: 2147483647
bd: -1
bx: ffffffff
bu: 4294967295
【问题讨论】:
Nit:这只是所谓的“铸造”。 “排版”是指您在电视或电影中看到同一演员扮演同一类型的角色。 【参考方案1】:当您将int
分配给short
时,如果该值不能在short
( [-2^15, 2^15 - 1], 2 的补码) 的范围内表示,则结果是实现定义的。
6.3.1.3 有符号和无符号整数
当一个整数类型的值被转换为另一个整数类型时 除 _Bool 以外,如果该值可以用新类型表示,则 不变。否则,如果新类型是无符号的...否则, 新类型已签名,并且无法在其中表示值;任何一个 结果是实现定义的或实现定义的 发出信号。
至于“实现定义”,它意味着行为取决于编译器、体系结构等。具体而言,您可能已经看到,一种可能的结果是简单地丢弃高位。在这种情况下,这会导致 11111111 11111111
。
另一个可能的结果是它被“四舍五入”到该范围内的最大值。在这种情况下就是01111111 11111111
。但我不记得哪个实现是这样的。
但无论哪种方式,都不要依赖它。
【讨论】:
请您澄清一下“定义的实现”是什么意思 @JonSmith 这意味着一个实现(编译器,架构,...)可以决定它做什么。 @JonSmith 他基本上意味着每个实现在许多方面都会有所不同,这将定义这个问题的答案。在字节顺序或 int 和 short 的表示等术语上有所不同 谢谢大家,非常感谢。【参考方案2】:C 或任何其他语言中的任何整数都以某些字节的形式存储(C 中为 4 个字节,如果您使用 32 位 C 编译器,通常大小为 int
取决于编译器),当您将其类型转换为 @ 987654322@ 并从内存中读取或分配给任何变量,因为short
指示编译器将值作为short int
读取,所以只读取或分配低 2 个字节。
在您的情况下,整数是二进制的01111111 11111111 11111111 11111111
,因此,当类型转换为short
时,它被读取为11111111 11111111
(低2个字节),这是-1
的16位二进制表示(当然,如果它的signed short
,默认情况下)。
我的意思是,假设你有一个int a = 0x7fffffff
存储在地址说1234
,那么a
的内存表示将是:
Memory Address: 1237 1236 1235 1234
Value: 01111111 11111111 11111111 11111111
当您将其读取为 short
时,仅读取低 2 个字节(地址 1235 和 1234)。
现在将它们读取为short
(或有符号短)意味着您希望数字的 MSB被编译器处理为符号位。由于Sign bit = 1
表示它是一个负数,并且如果您知道2 的补数格式(C 编译器使用它来表示整数),那么二进制中的数字11111111 11111111
等于十进制中的-1
。
此外,当您使用%u
或打印short int
值时,它被视为unsigned
,MSB(这一次)贡献于幅度,而不是符号位。
我还想补充一点:从short
到int
的类型转换。
每当您将 short
类型转换为 int
时,就像您在中所做的那样:
short b = (short)a;
printf("\nbu: %u",(int)b);
符号位填充了所有额外的高位,因此11111111 11111111
变为11111111 11111111 11111111 11111111
,即无符号十进制中的4294967295
。
如果您尝试类型转换01111111 11111111
而不是11111111 11111111
,那么它将被提升为00000000 00000000 01111111 11111111
,因为符号位是0
。
希望你能理解我的解释。
【讨论】:
@JonSmith 显然,是的,在你的特殊情况下。 @H2CO3 :感谢您指出这一点!我曾在 16 位编译器上工作过,即使那样我也犯了那个错误,我的错!现在我已经更正了。以上是关于解释类型转换如何在 C 中从 int 到 short 的位级别工作的主要内容,如果未能解决你的问题,请参考以下文章