首页 > C > 数据类型与变量 阅读:57,774

类型强制转换与自动转换

< 上一页 tyedef定义新类型 常量 下一页 >

在了解了数据的类型之后,需要进一步了解的是数据类型之间的转换。在C语言中,不同数据的类型是可以相互转化的。即在内存中存放的数据,可以按照不同的数据类型来解析。将一种数据类型显示的转换为另外一种类型叫强制转换;而非显示的转换则叫自动转换。

强制转换的格式为:(类型说明符)(表达式)。比如(int)a,将a的类型强制转化为int类型,(float)x+y),将x+y的结果强制转化为float类型。下面就是一些强制转换的例子:

char c  =‘a’;

short i = (short)c;

int a = (int)i;

long b = (long)a;

float c = (float)b;

double d = (double)c;

上面的转换都是从宽度短的转换为宽度大的。当把一个宽度短的数据类型到宽度大的数据类型转换的时候,是用符号位填充多出的位数。比如要把1个字节的正数00110101转换为2个字节的数据的时候,多出的8位将用符号位0来填充,因此转换后的数据为:00000000 00110101,而把1个字节的负数10110100转换为2个字节的数据的时候,多出的8位将用符号位1来填充,因此转换后的数据为:11111111 10110100

下面的例子是把宽度长的转换为宽度短的,这个过程可能会造成数据的丢失:

int x = 0x12345678;

short y = (short)x;

当把占4个字节的x强转为占2个字节的y的时候,整数的高位2个字节将会被截断因此,y只保留了0x12345678中的低位2个字节0x5678

除了强制类型转换为,还有类型的隐式转换,包括在不同类型做算术运算以及赋值操作的时候。

在进行算术运算(加、减、乘、除、取余以及符号运算)时,不同类型数据必须转换成同一类型的数据才能运算,算术转换原则为:

整型提升:对于所有比int小的类型,包括char, signed char, unsigned char, short, unsigned short,首先会提升为int类型。

在进行运算时,以表达式中最长类型为主,将其他类型位据均转换成该类型,如:

(1)若运算数中有double型或float型,则其他类型数据均转换成double类型进行运算。

(2)若运算数中最长的类型为long型.则其他类型数均转换成long型数。

(3)若运算数中最长类型为int型,则char型也转换成int型进行运算。算术转换是在运算过程中自动完成的。特别地,表达式里有符号和无符号之间的转换:

包含longunsigned int,32位机器上都是4字节,所以均转换为unsigned long.

包含signedunsigned intsigned会转换为unsigned。比如将-1赋给8位的unsigned char,结果就是255

char c ='A';

short s = 10;

int i = 100;

float f = 3.14f;//--->double

printf("%g\n",f+c+s+i)

在上面的例子里,结算过程中,c,s,i,f都会转换为double类型,然后参与加法运算。

进行赋值操作时,赋值运算符右边的数据类型必须转换成赋值号左边的类型,若右边的数据类型的长度大于左边,则要进行截断或舍入操作。

char c ='A';

double d = 10.1;

int i = 5;

float f = 3.14f;

int value = c/i + f*d;

在上面的例子里,先计算c/ic将会自动转换为int类型,结果也为int类型,然后计算f*d,由于ffloatddouble,所以会自动将f转换为double,再和d做乘。最后将c/i的值隐式转换为double型,然后和f*d的结果相加,结果为double型,然后再截断转化为int类型,赋值给value

 

无论是强制转换或是自动转换,都只是为了本次运算的需要而对变量的数据长度进行的临时性转换,而不改变数据说明时对该变量定义的类型。比如(int)a,将a强制转换为int类型之后,a本来的类型和值都不会改变。

int main(void)

{

         int a= 10;

         float x = (float)a;

         printf(“a = %d, x = %f\n”, a, x);

         return 0;

}

在上面的程序里,将a强制转化为float类型之后赋值给x,然后将ax打印输出,a的值并没有因为这次强制转化而发生改变,而x却获得了a强制转化后的值。

如果一个运算符两边的运算数类型不同,先要将其转换为相同的类型,即较低类型转换为较高类型,然后再参加运算,转换规则如图所示。

其中,横向箭头表示必须的转换,如两个float型数参加运算,虽然它们类型相同,但仍要先转成double型再进行运算,结果亦为double型。 纵向箭头表示当运算符两边的运算数为不同类型时的转换,如一个long 型数据与一个int型数据一起运算,需要先将int型数据转换为long型, 然后两者再进行运算,结果为long型。所有这些转换都是由系统自动进行的, 使用时你只需从中了解结果的类型即可。

此外,当较低类型的数据转换为较高类型时,一般只是形式上有所改变, 而不影响数据的实质内容, 而较高类型的数据转换为较低类型时则可能有些数据丢失。

赋值中的类型转换

当赋值运算符两边的运算对象类型不同时,将要发生类型转换, 转换的规则是:把赋值运算符右侧表达式的类型转换为左侧变量的类型。具体的转换如下:

(1) 浮点型与整型

 将浮点数(单双精度)转换为整数时,将舍弃浮点数的小数部分,只保留整数部分。将整型值赋给浮点型变量,数值不变,只将形式改为浮点形式,即小数点后带若干个0。注意:赋值时的类型转换实际上是强制的。

(2) 单、双精度浮点型

 由于C语言中的浮点值总是用双精度表示的,所以float 型数据只是在尾部加0延长为double型数据参加运算,然后直接赋值。double型数据转换为float型时,通过截尾数来实现,截断前要进行四舍五入操作。

(3) char型与int

 int型数值赋给char型变量时,只保留其最低8位,高位部分舍弃。

 char型数值赋给int型变量时, 一些编译程序不管其值大小都作正数处理,而另一些编译程序在转换时,若char型数据值大于127,就作为负数处理。对于使用者来讲,如果原来char型数据取正值,转换后仍为正值;如果原来char型值可正可负,则转换后也仍然保持原值, 只是数据的内部表示形式有所不同。

(4) int型与long

 long型数据赋给int型变量时,将低16位值送给int型变量,而将高16 位截断舍弃。(这里假定int型占两个字节) int型数据送给long型变量时,其外部值保持不变,而内部形式有所改变。

(5) 无符号整数

 将一个unsigned型数据赋给一个占据同样长度存储单元的整型变量时(如:unsignedintunsigned longlongunsigned shortshort) ,原值照赋,内部的存储方式不变,但外部值却可能改变。

 将一个非unsigned整型数据赋给长度相同的unsigned型变量时, 内部存储形式不变,但外部表示时总是无符号的。

short s=-1;

unsigned short us=s;//有符号s赋值给无符号us

因为s-1,其补码为11111111 11111111。在将s赋值给us的时候,内部存储不会改变,但被当做无符号数来解析,因此就成为了unsigend short中最大的值。

< 上一页 tyedef定义新类型 常量 下一页 >

周哥教IT,分享编程知识,提高编程技能,程序员的充电站。跟着周哥一起学习,每天都有进步。

通俗易懂,深入浅出,一篇文章只讲一个知识点。

当你决定关注「周哥教IT」,你已然超越了90%的程序员!

IT黄埔-周哥教IT技术交流QQ群:213774841,期待您的加入!

二维码
微信扫描二维码关注