• C语言:表达式求值详解



    前言

    该篇文章是笔者之前一篇文章C语言操作符详解的后续补充:

    表达式求值的顺序一部分是由操作符的优先级和结合性决定。
    同样,有些表达式的操作数在求值的过程中可能需要转换为其他类型。

    本文将介绍隐式类型转换、算术转换、和操作符的相关属性。预祝读者学业有成,天天进步!

    在这里插入图片描述


    提示:以下是本篇文章正文内容,下面案例可供参考

    一、隐式类型转换

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

    举个例子:

    int main()
    {
    	char a = 3;
    	char b = 127;
    	char c = a + b;
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    b和c的值被提升为普通整型,然后再执行加法运算。
    加法运算完成之后,结果将被截断,然后再存储于a中。

    在这里插入图片描述
    如何进行整形提升?
    整形提升是按照变量的数据类型的符号位来提升的

    //负数的整形提升
    char c1 = -1;
    变量c1的二进制位(补码)中只有8个比特位:
    1111111
    因为 char 为有符号的 char
    所以整形提升的时候,高位补充符号位,即为1
    提升之后的结果是:
    11111111111111111111111111111111
    
    //正数的整形提升
    char c2 = 1;
    变量c2的二进制位(补码)中只有8个比特位:
    00000001
    因为 char 为有符号的 char
    所以整形提升的时候,高位补充符号位,即为0
    提升之后的结果是:
    00000000000000000000000000000001
    
    //无符号整形提升,高位补0
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    整形提升的例子:
    示例1:

    int main()
    {
    	char a = 3;
    	//整形3的补码:00000000 00000000 00000000 00000011
    	//但是我们这里的a只有1byte,也就是8bit
    	//所以a:00000011
    	
    	char b = 127;
    	//整形127的补码:00000000 00000000 00000000 01111111
    	//同理b:01111111
    	
    	char c = a + b;
    	//a和b都是char类型,自身大小都是1byte,所以这里计算的时候要整形提升
    	//因为都是正数,所以整形提升前面补0
    	//a:  00000000 00000000 00000000 00000011
    	//b:  00000000 00000000 00000000 01111111
        //a+b:00000000 00000000 00000000 10000010
    	//计算完后发生截断(char一共8字节,取后面8位)
    	//c:  10000010
    	printf("%d\n", c);
    	//以%d的形式打印,也就是以整形形式打印,这里c又发生了整形提升
    	//但是这里因为c是10000010,就认为它的最高位是1,也就是负数了
    	//负数整形提升是前面补1
    	//c补:11111111 11111111 11111111 10000010(内存里存的是补码)
    	//c反:11111111 11111111 11111111 10000001(负数反码=补码-1)
    	//c原:10000000 00000000 00000000 01111110(负数原码=反码符号位不变其他全变)
    	//我们打印的是原码,也就是-126
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    在这里插入图片描述
    ps:整形提升也就是发生在short和char这两个类型上,因为其他类型都比int型大

    示例2:

    //实例2
    int main()
    {
     char c = 1;
     printf("%u\n", sizeof(c));
     printf("%u\n", sizeof(+c));
     printf("%u\n", sizeof(-c));
     return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    在这里插入图片描述

    直接 sizeof( c ),c没有参加运算也不会有整形提升,所以大小还是1
    但是sizeof(+c)和sizeof(-c)进行了运算,所以会有整形提升,也就是变成4字节了

    二、算术转换

    如果某个操作符的各个操作数属于不同的类型,那么除非其中一个操作数的转换为另一个操作数的类
    型,否则操作就无法进行。下面的层次体系称为寻常算术转换。

    long double
    double
    float
    unsigned long int
    long int
    unsigned int
    int
    //从下往上进行转换,eg:int->long double
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

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

    举个例子:

    int main()
    {
    	int a = 4;
    	float b = 4.1f;
    	float c = a + b;//会把int类型的a算术转换成float类型,再与b进行计算
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    三、操作符的属性

    复杂表达式的求值有三个影响的因素。

    1. 操作符的优先级
    2. 操作符的结合性
    3. 是否控制求值顺序。

    两个相邻的操作符先执行哪个?取决于他们的优先级。
    如果两者的优先级相同,取决于他们的结合性。

    下图中操作符优先级从上到下,是从高到底的
    结合性L-R表示从左向右,比如a+b+c是先算a+b,再算+c
    是否控制求值顺序,比如0&&(a+b*c/d),因为你&&左边是0,
    所以右边根本不会计算,这就控制了求值顺序了

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

  • 相关阅读:
    Day24---二叉树专题
    【ARM Coresight Debug 系列 17 -- ARM Debug Vector Catch 详细介绍】
    uniGUI之主窗口折叠UI之UniTreeMenu(32-2)
    论文阅读《Nougat:Neural Optical Understanding for Academic Documents》
    Ceph入门到精通-sysctl参数优化
    高精读整数加法【循环总结】
    人工智能时代大模型算法之文心大模型4.0
    【go语言】条件,选择,循环和特殊语句
    《机器学习分类器 二》——朴素的贝叶斯算法,项目实践,算法实践。
    《Python+Kivy(App开发)从入门到实践》自学笔记:简单UX部件——Slider滑块
  • 原文地址:https://blog.csdn.net/m0_57180439/article/details/126085067