整形之间的强制转换
在强制类型转换中,我们常用的整形强制转换有无符号和有符号类型的强制转换。所以首先我们得介绍一下计算机中存储数字的方式,计算机中通常以补码的形式来存储数据,以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。使用强制转化时会产生越界输出
总结
到此这篇关于C语言强制类型转换规则的文章就介绍到这了,更多相关C语言强制类型转换内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!