正文

[065] 赋值运算中的类型转换2006-11-11 21:28:00

【评论】 【打印】 【字体: 】 本文链接:http://blog.pfan.cn/wentao/20222.html

分享到:

    如果赋值运算符两侧的类型不一致,但都是数值型或字符型时,在赋值时要进行类型转换。

<1> 将实型数据(包括单、双精度)赋值绐整型变量时,舍弃实数的小数部分。如i为整型变量,执行“i=3.56”的结果是使i的值为3,在内存中以整数型式存储。

<2> 将整型数据赋绐单、双精度变量时,数值不变,但以浮点数形式存储到变量中,如将23赋值绐float变量f,即f=23,先将23转换成23.00000,再存储在f中。如将23赋绐double型变量d,即d=23,则将23补足有效位数字为23.00000000000000,然后以双精度浮点形式存储到d中。

<3> 将一个float型数据赋绐double变量时,数值不变,有效位数扩展到16位,在内存中以64位(bit)存储。将一个double型数据赋绐float变量时,截取其前面7位有效数字,存放到float变量的存储单元(32位)中。但应注意数值范围不能溢出。如:
float f;
double d = 123.456789e100;
f = d;
就出现溢出的错误。

 为了验证是否真的会溢出,写如下程序试验:

#include <stdio.h>
#include <string.h>
int main()
{
    float f;
    double d = 123.456789e100;
    f = d;
    printf("%f\n", f);
    return 0;
}

在TC(Win-TC)中运行会溢出,程序会自动退出,无任何显示( TC中欲使结果窗口停留,需在最后加一句getch(); )。而在VC中运行可以得到如下结果:

=================================================================================
12345678900000001000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000.000000
=================================================================================

分析一下,从4开始,到中间那个1共13位(此位非彼位'bit'哦),再从这个1算到最后是87位,合在一起刚好是100位,说明这个结果是正确的,并未溢出。看来数据类型在不同的编译器中的存储形式和表示方法还是有区别的!

<4> 字符型数据赋绐整型变量时,由于字符只占1个字节,而整型变量为2个字节,因此将字符数据(8位)放到整型变量的低8位中。有两种情况:
-1- 如果所用系统将字符处理为无符号的量或对unsigned char型变量赋值,则将字符的8位放到整型变量低8位,高8位补零。
-2- 如果所用系统(如Turbo C)将字符处理为带符号的(即signed char),若字符最高位为0,则整型变量高8位补0; 若字符最高位为1,则高8位全补1。这称为"符号扩展",这样做的目的是使数值保持不变,如变量c以整数形式输出为-2,将c赋绐int型变量i后i的值也是-2。

<5> 将一个int、short、long型数据赋绐一个char型变量时,只将其低8位原封不动送到char型变量(即截断)。例如:

int i = 289;
char c = 'a';
c = i;

 由于int型变量i为289,即二进制的0000000100100001,截断赋绐c后就变成了00100001,即十进制的33,如果用"%c"输出c, 将得到字符"!"(其ASCII码为33)。

<6> 将带符号的整型数据(int型)赋绐long型变量时,要进行符号扩展,将整型数的16位送到long型低16位中,如果int型数据为正值(符号位为0),则long型变量的高16位补0; 如果int型变量为负值(符号位为1),则long型变量的高16位补1,以保持数值不改变。反之,若将一个long型数据赋绐一个int型变量,只将long型数据中低16位原封不动地送到整型变量(即截断)。例如:

int a;
long b = 8;
a = b;

 由于long型变量b为8,即二进制的000000000 00000000 00000000 00001000,截断赋绐a后为00000000 00001000,a值仍为8,若long型数b超出了int型数的范围,截断后就与原值不等了。

<7> 将unsigned int型数据赋绐long int型变量时,不存在符号扩展问题,只需将高位补0即可。将一个unsigned类型数据赋绐一个占字节数相同的整型变量(如unsigned int -> int,unsigned long -> long,unsigned short -> short),将unsigned型变量的内容原样送到非unsigned型变量中,但如果数据范围超过相应整型的范围,则会出现数据错误。如:

unsigned int a = 65535;
int b;
b = a;

将a整个送到b中,由于b是int型,第1位是符号位,成了负数。根据补码知识可知,b值为-1。

 还是不放心,验证一下:

#include <stdio.h>
#include <string.h>
int main()
{
    unsigned int a = 65535;
    int b;
    b = a;
    printf("%d\n", b);
    return 0;
}

在TC中确实是按上述说法结果输出为-1。而在VC中输出的仍为65535,仔细一想,又是编译环境的差异,在VC中,int型数据是32位的而非16位( [034] 显示各种数据类型的长度),65535并未超出整型范围,此时int最大可表示4294967295(232-1),所以如果想说明上述问题时在VC中应将a赋值为4294967295,结果输出为-1。

<8> 将非unsigned型数据赋绐长度相同的unsigned型变量,也是原样照赋(连原有的符号位也作为数值一起传送)。如:

#include <stdio.h>
#include <string.h>
int main()
{
    unsigned int a = 65535;
    int b = -1;
    a = b;
    printf("%u\n", a);
    return 0;
}

%u是输出无符号数时所用格式。输出结果TC中为65535,VC中为4294967295。

以上的赋值规则看起来比较复杂,其实,不同类型的整型数据间的赋值归根到底就是一条:按存储单元中的存储形式直接传送。只要学过补码知识的,对以上规则是不难理解的。由于C语言使用灵活,在不同类型数据之间赋值时,常常会出现意想不到的结果,而编译系统并不提示出错,全靠程序员的经验来找出问题。


《C程序设计(第二版)》(谭浩强)

阅读(5802) | 评论(0)


版权声明:编程爱好者网站为此博客服务提供商,如本文牵涉到版权问题,编程爱好者网站不承担相关责任,如有版权问题请直接与本文作者联系解决。谢谢!

评论

暂无评论
您需要登录后才能评论,请 登录 或者 注册