孔乙己学C语言(9)

2.3数据类型的转换

企业里的朋友好像都特喜欢“水桶效应”这个理论,“一只水桶想盛满水,必须每块木板都一样平齐且无破损,如果这只桶的木板中有一块不齐,这只桶就无法盛满水。一只水桶能盛多少水,并不取决于最长的那块木板,而是取决于最短的那块木板”。可是我却有个不同的看法,如果把这个问题换个角度来看一下,比如把每块木板看做一个变量的精度,把盛水的容积看作是变量的和的精度,那么2+3.1415926+’a’的精度会取决于哪块木板呢?

问题描述:

这里给出一句看起来很简单的语句

int a=2+3.1415926

这里面涉及到两个问题,一是两个不同类型的数据相加,是如何进行计算的?二是等号右面的值的数据类型和等号左边的数据类型不同的时候,最后的结果以哪边为准?

实例分析:

int main(void){

         int a=2; *定义一个整型变量a */

         double b=3.1415926; /*定义一个双精度变量b*/

         printf("%d\n",sizeof(a+b)); /*将两个不同类型的变量求和,并查看计算结果的长度*/

         return 0;

}

 

 

int a=2;

0041139E  mov         dword ptr [a],2  /*将一个整型变量看作为dword32位机中dword表示32bit整数)*/

         double b=3.1415926;

004113A5  fld         qword ptr [__real@400921fb4d12d84a (415740h)] 

004113AB  fstp        qword ptr [b]  /*将一个双精度型变量看作为qwordqword表示64bit整数)*/

         printf("%d\n",sizeof(a+b));

004113AE  mov         esi,esp 

004113B0  push        8 

004113B2  push        offset string "%d\n" (41573Ch) 

004113B7  call        dword ptr [__imp__printf (4182B0h)] 

004113BD  add         esp,8 

004113C0  cmp         esi,esp 

004113C2  call        @ILT+295(__RTC_CheckEsp) (41112Ch) 

 

从上面的这个例子可以看出来,在进行加法的时候a+b的时候,不论什么数据类型都会转化为汇编的数据类型,编译器使用的汇编支持的数据类型常见的有以下几种

BYTE 

 8位无符号整数

WORD 

 16位无符号整数

DWORD

 32位无符号整数

QWORD

 64位整数

TBYTE

 80位整数

SBYTE

 8位有符号整数

SWORD

 16位有符号整数

SDWORD

 32位有符号整数

 

其中C语言中整形就先被转换成为了DWORD,而双精度型被转换成为了QWORD,然后这两个变量进行加法运算,这时的运算是浮点加法,而且32DWORDa被转换成为了64QWORD型,所以输出的结果长度为8(单位是字节)。在C语言的层面上来看,整型的a被转换成为了双精度。从这个例子来看的话,可以得到两点:

1 C语言的数据类型都会转换成汇编语言支持的数据类型。

2两种不同精度的数据进行运算,计算的根据是将低精度的数据转换为高精度的数据。

深入剖析:

实际上通常数据类型由短到长排列为charintlongfloatdouble。其中长度大的数据类型可以用来表示长度小的数据类型。

double ←float

long

unsigned

int ←char,short


因此,当运算符两边进行计算的数据类型如果不同的话需要遵循下面的这个图示,基本原则就是低精度要转换为高精度。

这里面有横向和纵向两种箭头,其中横向箭头表示必须要转换,即使是两个float相加,也是必须先要转换为精度更高的double类型来计算,纵向箭头表示在需要的时候转换,如果一个int和一个double相加,int需要转换为double类型,但是两个int类型相加的时候是不需要转换成其他类型的。这些操作都是编译器自动完成的。

第二个问题,例如int x=2+3.1415926

x的定义和2+3.1415926的类型不同,那么最后x的值又会什么呢?原则是以赋值运算符(=)的左边的为准。

这里有两种情形,一种是低精度的值赋值给高精度的变量,另一种是高精度的值赋值给低精度的变量。

这里给出几种常见的转换:

(1)       float->int

float转换为int时,将舍弃float的小数部分,只保留整数部分。

(2)       double->int

float->int

(3)       int->float

数值不变,只将变量形式改为浮点形式,在小数点后带若干个0

(4)       int->double

int->float

(5)       float->double

在变量的后面加上零补齐,延长为double型。

(6)       double-> float

double型数据转换为float型时,通过截尾数来实现,截断前要进行四舍五入操作。

(7)       int->char

char型变量被赋值为整型变量,保留低地址的8位,其余部分舍弃。

(8)       char->int 

这个转换涉及到不同编译器的不同处理方式,有的编译环境会将所有的char型都看做是正数,但是有的编译器却会将大于127的数转化为负数。

总结

需要注意的是在把一个高精度的数据转化为一个低精度的数据时,有时会出现部分数值位被抛弃,这是个很明显的问题,一个double需要64位保存,现在把这个64位的数据保存到一个32位的整型变量中,会出很大的偏差。另外尽量避免自动的数据类型转换,这点可以通过强制类型转换来实现。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值