【Amazing! C】操作符(二)

目录

前言

十一、隐式类型转换

11.1 整型提升

11.2 算数转换

12.3 操作符的属性


前言

        在C语言中,往往会操作不同类型的数据,此时,需要考虑类型转换。对此,C语言提供了两种不同类型的转换方式:隐式类型转换显示类型转换也称强制类型转换)。其中,隐式类型转换由编译器自行处理。

十一、隐式类型转换

        隐式类型转换分为整型提升算数转换

11.1 整型提升

        C语言的整型算术运算总是至少以缺省整型类型的精度来进行的。为获取这个精度,表达式中的字符短整型操作数在使用之前转换为普通整型这种转换成为整型提升

        那么,如何整型提升呢?

        整型提升的前提:只有当表达式中出现长度可能小于int型的整型值时,才需要对该值进行整型提升,转换为int或unsigned int,然后执行表达式的运算。

        char是signed char还是unsigned char,int是signed int还是unsigned int,等等,在C语言中并没有明确规定,而是取决于编译器。

        整型提升的规则:按照变量数据类型的符号位来提升的。

  • 无符号数,高位补0;
  • 有符号数,高位补符号位。

1.正数的整形提升:

char a = 1;
//0000 0000 0000 0000 0000 0000 0000 0001
//char类型只存放8个bit位
//所以,存放的是0000 0001,正数,原码就是补码
//所以,按符号位提升,8位最高位是0,所以,整型提升时,高位补0
//提升后:0000 0000 0000 0000 0000 0000 0000 0001

2.负数的整形提升:

char a = -1;
//1111 1111 1111 1111 1111 1111 1111 1111
//char类型只存放8个bit位
//所以,存放的是1111 1111,负数,存放的是补码
//所以,按符号位提升,8位最高位是1,所以,整型提升时,高位补1
//提升后的补码:1111 1111 1111 1111 1111 1111 1111 1111
//提升后的原码:1000 0000 0000 0000 0000 0000 0000 0001

        通过对整型提升的认识,我们很容易理解下面代码:

#include<stdio.h>

int main()
{
    char a = 5;
//0000 0000 0000 0000 0000 0000 0000 0101,但char类型只能存放8个bit位,即0000 0101
//存入的是:0000 0101	正数,原码就是补码
    
    char b = 126;
//同理:	0111 1110
    
    char c = a + b;//看到相加,char类型,都达不到整型大小,因此使用之前需要整型提升

//0000 0101	 signed char 按照符号位提升,8位看最高位是符号位0,因此,整型提升的时候,高位都补0
//0000 0000 0000 0000 0000 0000 0000 0101
//0111 1110
//0000 0000 0000 0000 0000 0000 0111 1110
//相加
//0000 0000 0000 0000 0000 0000 1000 0011

//char c中能放的是:  1000 0011

    printf("%d\n", c);//-125    //打印整型,又要以符号位进行整型提升
//1111 1111 1111 1111 1111 1111 1000 0011	补码
//1000 0000 0000 0000 0000 0000 0111 1100	取反
//1000 0000 0000 0000 0000 0000 0111 1101	原码

    return 0;
}

        此外,我们通过sizeof操作符,对整型提升进行验证:

#include<stdio.h>

int main()
{
    char c = 1;
	printf("%u\n", sizeof(c));//1    //sizeof(c),c没有参与运算,故就是求char类型大小
	printf("%u\n", sizeof(+c));//4	整型提升
	printf("%u\n", sizeof(-c));//4	整型提升
//sizeof(+c),sizeof(-c),c参与运算,整型提升为int,故就是求int类型大小

    return 0;
}

11.2 算数转换

        算数转换也属于隐式转换的一种,我们刚刚讨论的是类型小于整形的情况,算术转换的都是大于等于int类型的数据。如果某个操作符的各个操作数属于不同的类型,那么计算是无法进行下去的,除非将这些操作数全都转化为同一类型。因此,编译器是按照下图中由下向上转换的逻辑将不同的数据类型转换为相同。

  • long double
  • double
  • float
  • unsigned long int
  • long int
  • unsigned int
  • int

        如果某个操作数的类型在上面这个列表中排名较低,那么首先要转换为另外一个操作数的类型后执行运算。例如:

#include<stdio.h>

int main()
{
    int i = -1;
    if(i < sizeof(i))
    {
        printf("1\n");
    }
    else
    {
        printf("2\n");
    }
    
    return 0;
}

        代码执行结果为:

        单看这个代码,sizeof(-1)的计算结果是4,-1<4应该输出1,但是结果却得到2。

        究其原因,我们之前提到过,sizeof的返回值为size_t类型,在C中被定义为无符号整型类型,即unsigned int。所以,按照算数转换的规则,int i要转换为unsigned int。转换之后是一个非常大的数字,因此程序执行打印2。

12.3 操作符的属性

        C语⾔的操作符具有优先级结合性两个属性,这两个属性决定了表达式的计算顺序,在此过程中,我们还需要考虑是否控制求值顺序。我们通过代码进行理解:

#include<stdio.h>

int main()
{
	//优先级:相邻操作符,优先级高的先计算
	int a = 3 + 5 * 4;
	//结合性:相邻操作符优先级相同的情况下,结合性才有作用
	int b = 3 + 4 + 5;//从左向右结合

	return 0;
}

        值得注意的是,下面代码的写法是有问题的:

int main()
{
	a* b + c * d + e * f;//当a b c d e f分别是表达式时,计算将会出现问题,因此,表达式应该拆分写

	return 0;
}

C语言操作符优先级参照:https://zh.cppreference.com/w/c/language/operator_precedence

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值