C语言隐式类型转换和整型提升

C语言隐式类型转换
算术运算式中,低类型转换为高类型
赋值表达式中,表达式的值转换为左边变量的类型
函数调用时,实参转换为形参的类型
函数返回值,return表达式转换为返回值类型

算术运算符中的转换规则:

double ←── float 高
↑
long
↑
unsigned
↑
int ←── char,short 低

对于上面的隐式类型转换规则,绝大多数学c语言或者说学编程的人都知道。
那下面我们看一个有趣的例子吧:

#include <stdio.h>

int main()
{
    int i = -2;
    unsigned int j = 1;
    
    if( (i + j) >= 0 ){
        printf("i+j>=0\n");
    }
    else{
        printf("i+j<0\n");
    }
    
    printf("i+j=%d\n", i + j);
    
    return 0;
}


你觉得会有怎么样的输出呢,大家肯定会觉得简单啊。那先看一下运行结果吧:


看着上面的规则,对着输出,有点懵了,还能有这样的操作嘛?
来分析一下,在计算时,转换为高类型,即unsigned int,判断>0,这里感觉没有错。
那为什么输出-1,跟我们正常算-2+1的结果一样呢。我们都知道计算机是补码存储,-2+1的unsigned int结果是0xffffffff,但是对于输出的  %d  其实是int类型,也就是按照int类型打印出来,所以自然打印就是-1了。
————————————————

这样一个题,据说是微软面试题:

unsigned int i=3;
cout<<i * -1;

问结果是多少。

第一反应:-3。不过结果似乎不是这样的,写了个程序,运行了一下,发现是:4294967293。很诡异的一个数字,怎么也想不明白为什么会是这么个奇怪的数字。但是在我发现这数的十六进制数是FFFFFFFD时,我想我已经离答案很近了...

在表达式i*-1中,i是unsigned int型,-1是int型(常量整数的类型同enum),按第5条可以知道-1必须转换为unsigned int型,即0xffffffff,十进制的4294967295,然后再与i相乘,即4294967295*3,如果不考虑溢出的话,结果是12884901885,十六进制0x2FFFFFFFD,由于unsigned int只能表示32位,因此结果是0xfffffffd,即4294967293。

--------------------------------------------------------------

C/C++中规定了一组内置类型的隐式类型转换规则,用于类型不一致的运算过程中。

算术运算,如 int + short + double 时,int和short的变量会隐式转换为double,再与double进行加法。
关系运算,如 if ( int < unsigned int),会转换为较宽类型的unsigned int
赋值运算,如int = double,double的变量将会被截断成int,然后赋值给左边
函数返回,如fun()返回值为double,函数实现中,却return int,此时会将int隐式转换为double返回。
函数返回后 赋值给变量,如int = fun(),会将fun()返回的double类型转换为int。
      算术运算和关系运算的类型转换原则是转换为表达式中的最大宽度的类型。赋值运算和函数返回值相关的 转换原则是 按照目标类型进行转换。

 

       除了上面的隐式类型转换场景,C/C++还规定了另外一种需要进行隐式数据类型转换的场景:整值提升(integral promotion)。如果 表达式(如 算术计算和 关系判断)中的所有数据类型都小于int (小于int的有 枚举类型,bool、char、unsigned char、short ),则会将这些数据类型全部提升为int或unsigned int,提升后再进行表达式计算,计算后再进行截断得到最终结果。这个过程就是整形提升,提升规则:有符号的在左边补上符号位,无符号的在左边补上0。注:如果表达式中有数据类型大于int,其他小于int的类型会隐式转换为表达式中的最大宽度的类型。

       整型提升的意义,百度有以下解释:表达式的整型运算要在CPU的相应运算器件内执行,CPU内整型运算器(ALU)的操作数的字节长度一般就是int的字节长度,同时也是CPU的通用寄存器的长度。因此,即使两个char类型的相加,在CPU执行时实际上也要先转换为CPU内整型操作数的标准长度。通用CPU(general-purpose CPU)是难以直接实现两个8比特字节直接相加运算(虽然机器指令中可能有这种字节相加指令)。所以,表达式中各种长度可能小于int长度的整型值,都必须先转换为int或unsigned int,然后才能送入CPU去执行运算。
————————————————
------------------------------------------------

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值