天天看点

c语言数据类型转换

数据类型及其占计算机中的字节大小。

c语言数据类型转换

 不同类型数据间的混合运算与类型转换

        在C语言中,自动类型转换遵循以下规则:

c语言数据类型转换
c语言数据类型转换

  ①若参与运算量的类型不同,则先转换成同一类型,然后进行运算

  ②转换按数据长度增加的方向进行,以保证精度不降低。如int型和long型运算时,先把int量转成long型后再进行运算

            a、若两种类型的字节数不同,转换成字节数高的类型

            b、若两种类型的字节数相同,且一种有符号,一种无符号,则转换成无符号类型

   ③所有的浮点运算都是以双精度进行的,即使是两个float单精度量运算的表达式,也要先转换成double型,再作运算.

   ④char型和short型参与运算时,必须先转换成int型

   ⑤在赋值运算中,赋值号两边量的数据类型不同时,赋值号右边量的类型将转换为左边量的类型。

        强制类型转换一般格式如下:

            (类型名)(表达式)

        这种强制类型转换操作并不改变操作数本身

首先进行一个实验,分别定义一个signed int型数据和unsigned int型数据,然后进行大小比较:

unsigned int a = 20;signed int b = -130 ;b?还是b>a?实验证明b>a,也就是说-130>20,为什么会出现这样的结果呢?

这是因为在C语言操作中,如果遇到无符号数与有符号数之间的操作,编译器会自动转化为无符号数来进行处理,因此a=20,b=4294967166,这样比较下去当然b>a了。

unsigned int a=20; signed int b=-130;a + b结果输出为4294967186,同样的道理,在运算之前,a=20,b被转化为4294967166,所以a+b=4294967186

减法和乘法的运算结果类似。  unsigned int i=3;i * -1;问结果是多少

列子

c语言数据类型转换

 为什么 7.5 用%d输出的是0?分析如下:

        答:首先来了解下printf的输出格式,int 和 long int 都是32位的(4个字节),用%d输出;float 、double都是%f输出,但 float 是32位的(4个字节),double 是64位的(8个字节),所以在参数传递的时候C语言统一将 float 类型数值传换为 double 类型再传入 printf 函数。如果是32位整型则输出格式为%lld。

为什么float非要转成double类型呢?

   答:因为printf格式控制浮点型输出只有%f,所以统一按doube类型输出,不像整型有32位的%d或%ld,64位的有%lld,这就将32位整型和64位整型用不同的格式控制分开了,而%f则没有,所以printf输出的浮点数其实是统一遍历了64位内存,如果float传入printf没有进行转换,那么printf输出高32位数据将不可预知,printf输出结果也就不正确了,因此传入printf的浮点数都会被编译器隐含转成double类型。

下面来讲一下  float a=7.5f ; printf("%d",f)输出为0的情况:

   答:%d只输出低32位的数据,并将这些32位二进制以十进制数输出,编译器首先将 7.5从float类型转换为double类型,假设7.5在内存中的存放方式0x40f00000,转换成double类型在内存中的数据就是这个0x401e000000000000,这个内存数据可以很明显看出低32位全是0,而%d则只能截取到低32位,所以这个以%d输出7.5的数值当然是 0了。如大家不相信可以用%lld 输出看看,这个%lld就很读到低64位数据,读出的结果就是0x401e000000000000,在屏幕上看到一个很大的十进制数。

c语言数据类型转换

float f=7.5f;   如果用printf("%d",f);输出的是0。 但float型用%d输出是否一定是0 ?        答案肯定不都是0;

如果我一定要输出7.5在内存中的存放方法怎么办呢?

     答:可以用printf("%d",*(int *)&f);这里做了一下处理,不是直接把a传进来,把a所在地址里的内容处理了一下,不管a是什么类型,只对地址进行操作,利用(int *)&f,将a所在地址中的内容0x40f00000直接当成 int 类型传给printf,int 的类型数据不会再转成double类型了,所以输出正常,这个只是针对浮点型数据只占低32位,如果输出64位还得用%lld格式控制输出。如果用printf("%d",(int)a),输出行不行,这个强制类型转换只针对a的数据类型进行转换,7.5转换 int 类型是7,而上面的*(int *)&f,是对内存中的实际存储数据进行操作,蔽开数据类型这一层面,只将这个数据0x40f00000直接转成int类型输出。而(int)f,要先看a的类型,C语言会根据所要数据类型,对内存存储的数据进行改变,以便可以用int类型正确解析内存数据。

如果用printf("%d",(float)f),输出什么?

  答:输出的是0,这个只是将a的float类型还转成float类型,还是自动转成doube类型,传给printf函数。

***********************int类型%f格式输出************************************

如果定义了int a=0x40f00000;用printf("%f",f)输出的结果是多少呢?

   答案是0,至少我们看的屏幕上显示的是0.000000,实际值可不是0啊,只是我们显示的精度只能有15位小数,而实际的数据可能很小很小,0.0000....000几百个0后会有几个有效数据,我们分析一下。

   首先C语言把a传进printf,因为a是整型,所以不会自动转成double型数据,直接将0x40f00000传进printf,而%f寻的是64位内存,就把0x0000000040f00000这个内存中的数据当成浮点型输出来,那浮点型的数据是多少呢,又是怎么存储的呢?

64位浮点数的存放方式:

        63位                 62~52位                   51~0位

       1个符号位              11个阶数                 52个尾数

       从0x0000000040f00000来看

        1)符号位是0,表示正

        2)阶数是0,表示-1023 + 1023 = 0,用指数表示:1.#*2^-1023,‘#’是代表尾数。

        3)尾数就是,0x0000040f00000

        4)浮点二进制表示

 2#1.0000000000000000000001000000111100000000000000000000*2^(-1023),-1023次方可想而知有多小。

    这就是为什么我们的int型数据用%f输出是0.000000的原因。

5. 总结:

通过以上实验,我验证了原假设基本正确:

格式输出函数printf()根据类型字符%以及变量名,就可以根据数据首地址+读取长度的方式输出数据。

但是,还要注意其中的一些细节:

(1)用%d输出float类型数据时,在参数传递的时候C语言统一将 float 类型数值传换为 double 类型再传入 printf 函数。而%d只截取低32位数据,所以得到的数字不是相应浮点数的二进制码。

(2)int类型%f格式输出,%f寻的是64位内存,所以输出的数据可能很小(比如2^-1023),那么结果是0.

继续阅读