当前位置:编程学习 > C/C++ >>

数据类型转换 符号扩展

================         =   关于符号扩展 =            ===================
一、短数据类型扩展为长数据类型

1、要扩展的短数据类型为有符号数的

      进行符号扩展,即短数据类型的符号位填充到长数据类型的高字节位(即比短数据类型多出的那一部分),保证扩展后的数值大小不变

如1:char x=10001001b;   short y=x;  则y的值应为11111111 10001001b;

    2:char x=00001001b;   short y=x;  则y的值应为00000000 00001001b;

2、要扩展的短数据类型为无符号数的

     进行零扩展,即用零来填充长数据类型的高字节位


如1:unsigned char x=10001001b;   short y=x;  则y的值应为00000000 10001001b;

    2:unsigned char x=00001001b;   short y=x;  则y的值应为00000000 00001001b;

二、长数据类型缩减为短数据类型

    如果长数据类型的高字节全为1或全为0,则会直接截取低字节赋给短数据类型;如果长数据类型的高字节不全为1或不全为0,则转会就会发生错误。

三、同一长度的数据类型中有符号数与无符号数的相互转化

     直接将内存中的数据赋给要转化的类型,数值大小则会发生变化。另短类型扩展为长类型时,但短类型与长类型分属有符号数与无符号数时,则先按规则一进行类型的扩展,再按本规则直接将内存中的数值原封不动的赋给对方。

附:有符号数的转换


  从 到 方法
char short 符号位扩展
char long 符号位扩展
char unsigned char 最高位失去符号位意义,变为数据位
char unsigned short 符号位扩展到short;然后从short转到 unsigned short
char unsigned long 符号位扩展到long; 然后从long 转到unsigned long
char float 符号位扩展到long; 然后从long 转到float
char double 符号位扩展到long; 然后从long 转到double
char long double 符号位扩展到long; 然后从long 转到long double
short char 保留低位字节
short long 符号位扩展
short unsigned char 保留低位字节
short unsigned short 最高位失去符号位意义,变为数据位
short unsigned long 符号位扩展到long; 然后从long转到unsigned double
short float 符号位扩展到long; 然后从long 转到float
short double 符号位扩展到long; 然后从long 转到double
short long double 符号位扩展到long; 然后从long 转到double
long char 保留低位字节
long short 保留低位字节
long unsigned char 保留低位字节
long unsigned short 保留低位字节
long unsigned long 最高位失去符号位意义,变为数据位
long Float 使用单精度浮点数表示。可能丢失精度。
long double 使用双精度浮点数表示。可能丢失精度。
long long double 使用双精度浮点数表示。可能丢失精度。
 
 


无符号数的转换


  从 到 方法
unsigned char char 最高位作为符号位
unsigned char short 0扩展
unsigned char long 0扩展
unsigned char unsigned short 0扩展
unsigned char unsigned long 0扩展
unsigned char float 转换到long; 再从 long 转换到float
unsigned char double 转换到long; 再从 long 转换到double
unsigned char long double 转换到long; 再从 long 转换到double
unsigned short char 保留低位字节
unsigned short short 最高位作为符号位
unsigned short long 0扩展
unsigned short unsigned char 保留低位字节
unsigned short unsigned long 0扩展
unsigned short float 转换到long; 再从 long 转换到float
unsigned short double 转换到long; 再从 long 转换到double
unsigned short long double 转换到long; 再从 long 转换到double
unsigned long char 保留低位字节
unsigned long short 保留低位字节
unsigned long long 最高位作为符号位
unsigned long unsigned char 保留低位字节
unsigned long unsigned short 保留低位字节
unsigned long float 转换到long; 再从 long 转换到float
unsigned long double Convert directly to double
unsigned long long double 转换到long; 再从 long 转换到double

---------------------------------------------------------

                                          符号扩展,零扩展,以及缩减

         数现代高级程序设计语言允许程序员使用包含不同大小的整数对象的表达式。那么,当一个表达式的两个操作数大小不同的时候,会发生什么呢?有些语言会报错,而其他的语言则会自动将操作数转换成一个统一的格式。这种转换是有代价的,因此,如果你不希望编译器在你不知情的情况下自动加入各种转换到你原本非常完美的代码中,就需要掌握编译器是如何处理这些表达式的。

        进制补码系统中,同一个负数在不同大小的表示法中的表示是不同的。你不能在一个包含16位数的表达式中随意地使用8位有符号数,转换是必需的。这种转换,以及其逆操作(将16位数转换为8位)就是符号扩展(sign extension)与缩减(contraction)操作。

      -64为例,其8位的二进制补码表示是$C0,而等效的16位二进制补码表示则是$FFC0。很显然,其位模式不一样。再看看数+64,其8位和16位表示分别是$40与$0040。一个很显然的事实就是,扩展负数的大小与扩展非负数的大小是完全不同的。

     个数从某个位数符号扩展到一个更大的位数很简单,只需要将符号位复制到新格式新增的高端各位即可,例如,为了将一个8位的数符号扩展到16位,只需将8位数的第7位复制到16位数的第8 .. 15位即可。而将一个16位数符号扩展到一个双字,只需要将第15位复制到双字的第16 .. 31位即可。

        理不同长度有符号数的时候,必须使用符号扩展。例如,在将一个字节量与一个字量相加的时候,在相加之前必须将字节量符号扩展到16位。其他运算可能又会需要符号扩展到32位。

表2-5  符号扩展举例

8位
 16位
 32位
 二进制补码表示
 
$80
 $FF80
 $FFFF_FF80
 %1111_1111_1111_1111_1111_1111_1000_0000
 
$28
 $0028
 $0000_0028
 %0000_0000_0000_0000_0000_0000_0010_1000
 
$9A
 $FF9A
 $FFFF_FF9A
 %1111_1111_1111_1111_1111_1111_1001_1010
 
$7F
 $007F
 $0000_007F
 %0000_0000_0000_0000_0000_0000_0111_1111
 
n/a
 $1020
 $0000_1020
 %0000_0000_0000_0000_0001_0000_0010_0000
 
n/a
 $8086
 $FFFF_8086
 %1111_1111_1111_1111_1000_0000_1000_0110
 

       处理无符号二进制数的时候,可以使用零扩展(zero extension)来将小位数的无符号数扩展到大位数的无符号数。零扩展非常简单——只需要用零来填充大位数操作数的高端各个字节即可。例如,为了将8位数$82零扩展到16位,只需要在高端字节中插入零,即得到$0082。

表2-6  零扩展举例

8位
 16位
 32位
 二进制补码表示
 
$80
 $0080
 $0000_0080
 %0000_0000_0000_0000_0000_0000_1000_0000
 
$28
 $0028
 $0000_0028
 %0000_0000_0000_0000_0000_0000_0010_1000
 
$9A
 $009A
 $0000_009A
 %0000_0000_0000_0000_0000_0000_1001_1010
 
$7F
 $007F
 $0000_007F
 %0000_0000_0000_0000_0000_0000_0111_1111
 
n/a
 $1020
 $0000_1020
 %0000_0000_0000_0000_0001_0000_0010_0000
 
n/a
 $8086
 $0000_8086
 %0000_0000_0000_0000_1000_0000_1000_0110
 

大多数高级语言编译器会自动处理符号扩展与零扩展,以下C语言的例子说明了它们是如何工作的:

signed char sbyte;     // C语言中的字符类型是一个字节

short int sword;          

补充:软件开发 , C++ ,
CopyRight © 2022 站长资源库 编程知识问答 zzzyk.com All Rights Reserved
部分文章来自网络,