C++类型转换本质

1 篇文章 0 订阅

C++类型转换本质

在讲类型转换之前,我们先说一下数字是怎么在计算机中存储的。其实数字在计算机中都是用二进制0,1表示的,比如说int a = 3,那么它在计算机中的存储格式为00000000000000000000000000000011。负数是以补码的形式存储的,关于补码可以自己去了解下,这涉及到源码反码的概念。

比int小的首先转换成int,unsigned int,long,unsigned long,long long,unsigned long long中最小的一种类型,前提是这种类型能容纳所有原先类型的值。比如说计算b + c时如果b和c都是char类型的话,那么首先把它们转换成int型再做加法。

(一)比较小的类型转换成比它大的类型会发生什么(如char 转换成int),这里又存在几种情况(如unsigned char 转int,char转int,unsigned char 转unsigned int,char转unsigned int)

(1)unsigned char转int(先把unsigned char提升,提升过程中高位全补0,如a为10,二进制表示00001010,先提升到32位为00000000000000000000000000001010,然后再转换成int)

(2)signed char转换成int,当signed char为负数时候提升到32位把填充位全填为1,当signed char为正数时候,高位全补0.当signed char为-128时二进制表示为10000000,首先提升为11111111111111111111111110000000,然后再转换成int,即int 的二进制表示也是11111111111111111111111110000000。a为10时二进制表示就为00001010,先提升到32位为00000000000000000000000000001010,然后再转换成int。

(3)char转换成unsigned int会怎么变化呢。当char为正数时,char先提升到32位,高位补0,然后再转换为unsigned int(就是把提升后的32为二进制给unsigned int)。当char为负数时,先提升到32位,高位补1,然后再把提升后的32位二进制给unsigned int。如下图,当char为10时,二进制表示为00001010,先提升为00000000000000000000000000001010,然后再转换成unsigned int,我们知道二进制为00000000000000000000000000001010的unsigned int还是10。当char为负数时,令char等于-128,先提升为11111111111111111111111110000000,然后再转换成unsigned int,我们知道二进制为11111111111111111111111110000000的unsigned int值为4294967168。

当小类型提升为大类型时首先提升为大类型的位数(如上面讲的8位提升为32位),然后再把提升后的二进制原封不动的给大类型。提升过程中高位补0还是补1只和小类型的正负有关。如果小类型是unsigned型的,高位一律补0。如果小类型是signed型的,那么看小类型数的符号为是0还是1,如果是0高位就补0,如果是1,高位就都补1。

(二)大类型转换成小类型时会被截断,只把大类型的低位给小类型。比如说大类型的二进制为00000000000000000000000110000000(int,384),当把这个值赋给char类型时,不管char是有符号的还是无符号的,都把二进制10000000赋给char,所以当char为有符号的时候值就是-128,当char是无符号的时候就是128。

(三)左移和右移。当这个数为无符号数的时候,不管对它进行左移还是右移都补0,如对00000000000000000000000010000000进行左移时得00000000000000000000000100000000,进行右移得00000000000000000000000001000000。当这个数为有符号数时,对它进行左移还是补0,但是对它进行右移就得看情况了。当它是负数时,进行右移就补1,当它是正数时就补0。如对00000000000000000000000010000000进行右移1位得00000000000000000000000001000000,对10000000000000000000000010000000进行右移得11000000000000000000000001000000。

数据类型转换本质原来有两个:

1.窄变宽:左边补符号位

#include<stdio.h>
int main(){
    char a=-1;          //1111 1111
    char b=1;            //0000 0001
    unsigned char c=1;    //0000 0001
    unsigned char d=255;    //1111 1111
    int e=a; //整形4字节,32位,符号位为1,因此左边补1111 1111 1111 1111 1111 1111 1111 1111
    printf("%d,%x\n",e,e);    
    int e=b;    //符号位为0,因此左边全补0为0000 0000 0000 0000 0000 0000 0000 0001
    printf("%d,%x\n",e,e);
    int e=c;    //无符号型符号位为0,因此左边全补0为0000 0000 0000 0000 0000 0000 0000 0001
    printf("%d,%x\n",e,e);
    int e=d;    // 同理无符号型符号为0因此给左边补0为0000 0000 0000 0000 0000 0000 1111 1111
    printf("%d,%x\n",e,e);
}

2.宽变窄:保留低数据

#include<stdio.h>
int main(){
    int a=0x12345678;
    int b=0xff347890;
    char c=a; //0x78  0111 1000
    char d=b;    //0x90 1001 0000,0111 000
    printf("%d,%x\n",c,c); //120 78
    printf("%d,%x\n",d,d); //符号位为-1取反+1 -112,ffffff90
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值