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)。

但进行第二步转换时,值会由于截断而发生变化,而这个截断一般是高位截断(舍弃高位,保留低位):
c语言强制类型转换详解_第1张图片
如int类型的255(0000 0000 … 0000 0000 1111 1111)转化为8为的unsigned char类型时,前面的0将被截断,只保留低8位,即255(1111 1111),当然,若是转为8为的有符号char类型,则为-1(1111 1111)。截断是二进制层面的位数截断
,与实际值无关。

整形与浮点数的强制类型转换

我们都知道浮点数float类型一般遵循ieee754标准,有符号位,阶码和尾数:
c语言强制类型转换详解_第2张图片
与整形相同,符号位是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语言)