解释类型转换如何在 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(这一次)贡献于幅度,而不是符号位。

我还想补充一点:从shortint 的类型转换。 每当您将 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 的位级别工作的主要内容,如果未能解决你的问题,请参考以下文章

如何在目标 c 中从 int 转换为字符串:示例代码

如何在 C# 中从 MySQL 中检索 tinyint 的数据类型?

java基础--------运算符与类型转换

在 Hive 或 Impala 中从 int 转换为时间戳

在C#中如何将int类型强制转换为double类型

从类名转换的 C++ 指针类型 [关闭]