c语言强制类型转换详解
整形之间的强制转换
在强制类型转换中,我们常用的整形强制转换有无符号和有符号类型的强制转换。所以首先我们得介绍一下计算机中存储数字的方式,计算机中通常以补码的形式来存储数据,以8位数据为例,二进制与有符号数的对应关系为:
0 | 1 | 2 | … | 127 | -128 | -127 | … | -1 |
---|---|---|---|---|---|---|---|---|
0000 0000 | 0000 0001 | 0000 0010 | … | 0111 1111 | 1000 0000 | 1000 0001 | … | 1111 1111 |
无符号转有符号
0 | 1 | 2 | … | 127 | 128 | 129 | … | 255 |
---|---|---|---|---|---|---|---|---|
0000 0000 | 0000 0001 | 0000 0010 | … | 0111 1111 | 1000 0000 | 1000 0001 | … | 1111 1111 |
所以对于有符号数,首先最高位是正负的标志位。要将无符号数强制转化为有符号数时,其内存上的二进制是不会改变的,只是我们对它的解释变了,即无符号数128强制转化有符号数即-128。
当然这样引申出来的一种好处就是对于有符号数的判断,如
char a; ... if((a>=0)&&(a<80)) { .... }
可以使用强制转化,省去一个判断条件
char a; ... if( ((unsigned char)a) < 80) { .... }
有符号转无符号
将有符号数变成无符号数时,情况也类似,如8位的有符号数120转无符号也是120,但8位的-1转无符号则为255。所以当我们在有符号数的计算中,想保留大于等于0的数,不能通过强制转化来完成,必须得加判断:
char a,b,d;
unsigned char c;
....
c=(unsigned char)(a+b); (×):当运算结果小于0时c会异常,变成超级大数
d=a+b;
c = (d<0)?0:d; (√)
不同长度数字转化中的截断
比如我有一个8位的有符号数-1,要转换为一个16位的有符号数,那么结果仍旧是-1。首先我们要明确一点,那就是虽然8位的有符号数-1的二进制原本1111 1111,但载入32位的cpu中运算时,它将转化为32位的有符号数进行运算,即int类型的-1。所以对于char类型的数据,即使运算结果超过了该类型,其实也不会发生异常:
char a=127,b=127,c=127,e;
int d;
....
e=a+b+c; (×):当运算结果超过存储类型的表示范围时,会因截断产生错误
d=a+b+c; (√):32位的int类型足够存储结果。
所以我们如果把不同长度的数字进行类型转换,只有两个步骤:
1、将该数表示为32位
2、将32位数截断为结果类型
不过,可以确定的一点就是,进行第一步时,数的值不会发生变化:
比如8位有符号数-1(1111 1111)将转化为32位的-1(1111 1111 1111 1111 … 1111 111)。
而8位的无符号数255(1111 1111)转为32位时,也仍旧是255:(0000 0000…0000 0000 1111 111)。
但进行第二步转换时,值会由于截断而发生变化,而这个截断一般是高位截断(舍弃高位,保留低位):
如int类型的255(0000 0000 … 0000 0000 1111 1111)转化为8为的unsigned char类型时,前面的0将被截断,只保留低8位,即255(1111 1111),当然,若是转为8为的有符号char类型,则为-1(1111 1111)。截断是二进制层面的位数截断
,与实际值无关。
整形与浮点数的强制类型转换
我们都知道浮点数float类型一般遵循ieee754标准,有符号位,阶码和尾数:
与整形相同,符号位是1时代表负数,是0则为正数。而阶码代表小数点在哪儿,类似于科学计数法100会被表示为 1.0 × 10^2。详细的这里不介绍了,我们重点放在强制转化上:
对于一个int类型的数,只要在浮点数的表示范围内,便可以正确的转为浮点数格式。
但是对于一个浮点类型的数,在转化为整形时,则会只保留整数位,如:
int a= (int)0.1; 即a=0
int a= (int)1.1; 即a=1
int a= (int)1.5; 即a=1
int a= (int)-1.5; 即a=-1
所以如果要四舍五入之类的的,则不能靠强制转换,得用相关的函数。当然若是转为其他整形,则结果将有32位的整形结果进行截断得到。
当然,强制转换和 floor 这个函数的功能其实很像,floor函数的功能是向下取整:
int a= floorf(0.1); 即a=0
int a= floorf(1.1); 即a=1
int a= floorf(1.5); 即a=1
对于大于0的浮点数,他俩其实可以替换,而当小于0时,他俩区别很大:
int a= floorf(-0.1); 即a=-1
int a= floorf(-1.1); 即a=-2
int a=(int)-0.1; 即a=0
int a=(int)-1.1; 即a=-1
强制转化的结果,会产生正负0这种概念,如-0.9到0.9强制转化结果都为0。使用强制转化时会产生越界输出
更多推荐
所有评论(0)