C进阶 表达式求值
文章目录
一.表达式求值
二.隐式类型转换(整形提升与算术转换)
三.操作符的属性
前言
我们需要了解这个底层的知识,来帮助我们了解很多
一、表达式求值
表达式求值的顺序一部分是由操作符的优先级和结合性质决定的,同样,有些表达式转换为类型
(注:结合性:N/A无结合性 L-R从左到右 R-L从右到左)
案例:优先级:
int a = 4 + 6 / 3;
这个就是“/” 的优先级比“+”的优先级,先除在加。
结合性:
int b = 4 + 4 + 4;
这里体现了结合性,由于都是加号,优先级相同,所以考虑结合性,这里就是L-R从左向右
二,隐式类型转换
C整形算术运算总是至少一缺省整形类型来进行进度运算的 (注:缺省整形就是默认为整形)
由于(char类型,short类型等)是比整形的字节数要小的,为了获取这个精度表达式的char类型和short类型等都是在使用之前都是要被换为普通整形的,这个就是叫做整形提升。
(有这个存在的原因有很多种,比如跟cpu的线性宽度有关(有4和8字节), 这个可以大大提升cpu的获取数据的速度,减少运算时间,因为cpu的整形运算器的操作字节数一般都是一次性获取4字节,提升整形可以增加运算速度,也是寄存器的的通用的长度)
例子
char a = 2;
char b = 126;
char c = a + b;
//c的结果为多少
这里有char的范围但是呢,按照我们的正常的思路都是1+126 =127 (测试环境为vs2019)
这里的输出结果为-128,为什么不是127呢,这里就考虑到了整形提升,a与b都是char类型的都是1个字节,达不到int 4个字节的标准,所以发生了整形的提升 ,那么该怎么进行整形提升呢?
这个是以1和-1为例子讲述的整形提升(注:在利用char类型进行运算的时候,无论类型的大小是多少,只要小于int类型,就要进行整形提升)
这里以char a =5;char = 126;char c =a + b;//c是多少
注:1.截断:由于char类型只可以存储8位,但是有32位,所以有截断来存入
2.二进制运算:取2进1取0
3.char类型和其他的类型都是存储补码,注意在提升的时候,符号为不变
4. %d是取整数,所以也要进行整数提升
我们再来看一个代码:
#include<stdio.h>
int main()
{
char a = 0xb6;
short b = 0xb000;
int c = 0xb6000000;
if (a == 0xb6) printf("a");
if (b == 0xb6000) printf("b");
if (c == 0xb6000000) printf("c");
return 0;
}
在这个代码我们分别用了十六进制给a,b,c都赋予了值,然后来判断是否有整形提升,如果a和b都打印出来了,那么就是没有发生整形提升,如果没有则反之(环境测试vs2019)
根据vs测试的结果来看,这个a和b都是进行了整形提升,变成了与c一样的值,所以才没有打印出来
关于负数该怎么求取他的原码反码补码呢?
我们了解了整形提升到底是怎么弄的了,接下来我们来看个很容易错的题目:
#include<stdio.h>
int main() {
char c = 1;
printf("%u\n", sizeof(c));
printf("%u\n", sizeof(+c));
printf("%u\n", sizeof(-c));
}
这个是分别求这个sizeof() 大小,我们一般都是会认为为1的,但是你要知道+c他是一个表达式,想不到吧,我当时也想不到,后面才知道的,所以这个细节我们要很重视(用的vs2019测试)
这里的字节数后面都是4,总结%d+表达式是需要整形提升的
那么问题来了,如果不是char和short哪些,是double long 这些比int的字节数大的怎么办呢,这个时候我们就有了一个叫算术转换的东西
这个是算术转换的顺序表(部分):
比如你让类型的数据和float的数据相遇时,这个就会把int类型转换为float类型
三,操作符的属性
1.操作符的优先级 2.操作符的结合性 3.是否控制顺序求值(这些百度都是有表格可以看的)
问题表达式1:
a* b + c * e + d * f
我们来看这个代码
编译器看到这个会有很多的方法:
法一:1--a*b 2--c*e 3--d*f 4--计算第一个+ 5--计算第二个+
法二:1--a*b 2--c*e 3--计算第一个+ 4--d*f 5--计算第二个+
虽然两个计算的结果都是一样的,但是这些表达式的计算的顺序还是要知道的,如果后面项目是要a影响c再b影响f的时候,这个不可预测顺序是很荒唐的,没有为唯一的计算路径
改进方法:(a*b+c*e)+d*f 加一个括号就好了
问题表达式2;
c + --c;
这里有这个表达式,前置--的优先级是比+大的(以c=2为例子)
有两种解法:
这两种方法都是没有违背优先级的,但是运算的结果不一样
问题表达式3:
int main() {
int a = 1;
int b = (++a) + (++a) + (++a);
printf("%d", b);
}
这个代码呢也有两个算法:vs是12 Linux是10
所以我们不可以写出这种问题表达式出来,我们自己是无法掌握这些运算顺序的,所以我们就要了解优先级和结合性
总结
我们学习了整数提升,算术转换,表达式求值,几个问题表达式,我们就可以了解到结合性和优先级的总要性
原文地址:https://blog.csdn.net/2401_86738532/article/details/144000685
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!