C语言表达式求值(整型提升)

海哥  金牌会员 | 2024-12-13 00:35:20 | 显示全部楼层 | 阅读模式
打印 上一主题 下一主题

主题 881|帖子 881|积分 2643

一:优先级与结合性

        表达式求值的次序一部门是由利用符的优先级和结合性决定,有些表达式的利用数在求值的过程中可能需要转换为其他类型(是否存在整型提升或算术转换)。
        真正计算的时间先看相邻利用符的优先级决定先算谁,相邻利用符的优先级相同的情况下,看利用符的结合性决定计算次序
注意:即使有了优先级和结合性,表达式也不一定能求出唯一值
二:整形提升(隐式类型转换)

        C语言的整形算术运算总是至少以缺省整型类型的精度来进行的。为了得到这个精度,表达式中的字符和短整型利用数在利用之前被转换为平常整形,这种转换称为整型提升。
        整型提升是按照变量的数据类型的符号位来提升的,最高位(最左边)是符号位,符号位是1就在前面全部补上1,符号位是0就在前面全部补上0
三:整型提升底层原因

       表达式的整形运算要在CPU的相应运算器件内执行,CPU内整形运算器(ALU)的利用数的字节长度一般就是int的字节长度,同时也是CPU的通用寄存器的长度。因此即使两个char类型相加,在CPU执行时实际上也要先转换为CPU内整形利用数的标准长度
       通用CPU是难以直接实现两个8比特字节直接相加运算(虽然呆板指令中可能有这种字节相加指令)。以是,表达式中各种长度可能小于int长度的整型值,都必须先转换为int 或unsignerd int,才能送入CPU去执行计算。
四:整数截断的例子

char c = -1;  (-1是整数,4个字节,32个比特位,然而char是字符,1个字节,8个比特位,以是在存的时间就需要截断,只取最低为8位(从右往左8位))
10000000000000000000000000000001(-1的原码)
1111111111111111111111111111111111110(-1的反码)
1111111111111111111111111111111111111(-1的补码)
内存中存的是补码,用补码来截断,得到c存的补码
c存的补码就是11111111

五:char类型整数相加计算的底层逻辑


    char a = 5;
    00000000000000000000000000000101(5的原码反码补码)
    00000101(a的原码反码补码)
    char b = 126;
    00000000000000000000000001111110(126的原码反码补码)
    01111110(b的原码反码补码)
    char c = a + b;//a和b达不到一个整形大小,以是要进行整型提升
        00000000000000000000000000000101(运算时的a的原反补码)
        000000000000000000000000001111110(运算时的b的原反补码)
    二者相加
        00000000000000000000000010000011(运算时的c的原反补码)
    由于c是char类型,截断
    10000011(c的原反补码)最高位是符号位是1代表负数
    printf("%d\n", c);//打印-125
    这里是打印整形,c不够,需要进行整型提升,由于整型提升是按照变量的数据类型的符号位来提升的,整型提升后得到的是补码:
    11111111111111111111111111110000011(补码)
    11111111111111111111111111110000010(反码)
    10000000000000000000000001111101(原码)
    将原码转换为十进制数就是-125,故最终c = -125
六:char类型整数相加计算的轻便计算

如果每次计算都像第五点这样分析,对于人来说太慢了,这里讲一个轻便方法,钟表循环法,只需记住char类型的范围是-128到127之间(即最大值是127,最小值是-128),类比钟表循环方法
图一:从1点开始增加到12点(共12个数)
          15点是几点呢?15-12=3,完成了一次循环,然后从12开始走3下,就是3点
          20点是几点呢?20-12=8,完成了一次循环,然后从12开始走8下,就是8点
图二:从-128开始增加到127(中心包罗0,共256个数)
          131是多少呢?相当于从0开始顺时针走了131下,就是 -125
          782是多少呢?782-3*256=14,完成了3次循环,然后从0开始顺时针走14下,就是14
          736是多少呢?736-2*256=224,完成了2次循环,就是0开始顺时针走224下,就是 -32

         -131是多少呢?相当于从0开始逆时针走了131下,就是 125

         -782是多少呢?782-3*256=14,完成了3次循环,然后从0开始逆时针走14下,就是 -14

         -736是多少呢?736-2*256=224,完成了2次循环,就是0开始逆时针走224下,就是 32


七:类型不同赋值底层逻辑

      十六进制数是0x开头的,十六进制数最大值是15,用二进制表现就是1111,以是十六进制数的1位需要二进制数的4位来表现。 (用于16进制直接转换成二进制)
      二进制最高是32位,即十六进制最高是8位;二进制1位就是1个比特位,八个二进制位才是一个字节,十六进制1位就是4个比特位,两个十六进制位就是一个字节
char e = 0xbc;
    (b代表11,二进制就是1011,c代表12,二进制就是1100)以是转换成二进制是10111100,十六进制数本质上是一个整型,内存中应该是32位
       即:0xbc在内存中存的是00000000000000000000000010111100
       将一个整形赋给一个char类型,会进行截断,实际上存的e是10111100(8位,一个字节),最高位是1,计算机把e明白为一个负数
       简朴明白是:0xbc是一个整形,而e是一个char类型,将一个整形赋给一个char类型的时间会进行截断,实际上e存的并不是这个整形
       即:我们并没有真正把这个数赋给它(由于类型不一样),故而在背面比力的时间肯定不一样呢
if (e == 0xbc)
printf("e\n");//不会打印
        由于左边是一个char类型,右边是一个int类型(整型),不能直接比力,以是char会发生整形提升
        e在内存中存的是10111100(补码),最高位1,前面补充1得到11111111111111111111111110111100(补码)从而得到11111111111111111111111110111011(反码)
        从而得到10000000000000000000000001000100(原码)转换成十六进制就是0x80000044,可知它并不等于0xbc(0xbc相当于0x000000bc)
        实际上在前面已经知道了e其实是一个负数,而0xbc是一个正数,直接就不相等了
unsigned char e1 = 0xbc;
        这里和前面类似,不同在于,e1是无符号的以是虽然e1在内存中存的也是10111100,但是他是无符号的,最高位的1不是符号位,而就是一个真实的数,整型提升的时间前面都是加的0
if (e1 == 0xbc)
printf("e1\n");
//会打印
        即:整型提升后是00000000000000000000000010111100(原码反码补码)转换成十六进制就是0x000000bc就是等于0xbc
short r = 0xbc00;
        同理将一个整型赋值给一个短整型,会发生截断,以是r在内存中存的是1011110000000000(16位,两个字节)
if (r == 0xbc00)
printf("r\n");
//不会打印
        由于左边是一个short类型,右边是一个int类型(整型),不能直接比力,以是short会发生整形提升
        最高位是1,前面补充1,得11111111111111111011110000000000(补码)从而得到11111111111111111011101111111111(反码)
        从而得到10000000000000000100010000000000(原码)转换成十六进制就是0x80008800,可知并不相等
int t = 0xbc000000;
        整型赋值给整型,不会发生截断存的就是本身
if (t == 0xbc000000)    //类型相同不会发生整型提升,就是相等的
printf("t\n");//会打印
 
八:时候注意表达式的整型提升

char q = 1;
printf("%zu\n", sizeof(c));//1
printf("%zu\n", sizeof(+c));//4
printf("%zu\n", sizeof(-c));//4

(写成+c和-c的形式都是表达式的形式,只要是表达式运算的时间就会整型提升,于是c由一个字节变成4个字节)






免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

海哥

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表