文章目录

  • 1:算术操作符
  • 2:移位操作符(移动的是二进制序列中的补码)
    • 2.1:知识补充(原码,反码,补码与二进制)
    • 2.2:左移操作符(<<)
    • 2.2:右移操作符(>>)
      • 2.2.1:逻辑右移
      • 2.2.2:算术右移
  • 3:位操作符(运算用的是二进制位的补码)
    • 3.1:按位与操作符(&)
    • 3.2:按位或操作符(|)
    • 3.3:按位异或操作符(^)
  • 4.赋值操作符
    • 4.1:复合赋值符
  • 5:单目操作符
    • 5.1:逻辑反操作符(!)
    • 5.2:正值,负值操作符(+ -)
    • 5.3:取地址操作符和解引用操作符(& *)
    • 5.4 sizeof操作符
    • 5.5:按位取反操作符(操作的是补码)
    • 5.6:++,–操作符
    • 5.7:强制类型转换操作符
  • 6:关系操作符
  • 7:逻辑操作符
    • 7.1:逻辑与操作(&&)
    • 7.2:逻辑或操作(| |)
  • 8.条件操作符(三目操作符)
  • 9:下标引用、函数调用和结构体成员访问操作符
    • 9.1:下标引用
    • 9.2:函数调用操作符
    • 9.3:结构体成员访问
  • 10:操作符的属性
    • 10.1优先级
    • 10.2结合性
  • 11:表达式求值
    • 11.1:整型提升
      • 11.1.1整型提升的意义:
      • 11.1.2:如何进行整型提升
    • 11.2:算术转换
    • 11.3:问题表达式解析
      • 11.3.1:表达式1
      • 11.3.2:表达式2
      • 11.3.3:表达式3

嘻嘻,家人们,今天咱们来详解C语言中的操作符,好啦,废话不多讲,开干!

1:算术操作符

算术操作符呢其实就是我们日常生活中常见的加减乘除还有取余,这里博主就不具体展开讲了,就针对这些操作符中的小注意事项来进行讲解。

+ - *(乘法)/(除法) %(取余)
  • (1):除了%操作符以外,其他的几个操作符都可以作用于整数和浮点数。
  • (2):对于/操作符,如果两个操作符都为整数,则执行整数除法(即只保留整数部分,去除小数部分),而只要存在浮点数执行的就是浮点数除法
  • (3):%操作符的两个操作数必须为整数,返回的是整除之后的余数
#define_CRT_SECURE_NO_WARNINGS#include int main(){//得到的是小数,但是是放入整型数据,因此得到的是3printf("7 / 2= %d\n", 7 / 2);printf("7.0 / 2.0= %d\n", 7.0 / 2.0);/**只要浮点数存在,那么执行的就是浮点数除法*/printf("7.0 / 2= %lf\n", 7.0 / 2);printf("7.0 / 2.0= %lf\n", 7.0 / 2.0);//%操作符的两个操作数必须为整数,返回的是整数之后的余数printf("7 %%2 = %d\n", 7 % 2);return 0;}

2:移位操作符(移动的是二进制序列中的补码)

2.1:知识补充(原码,反码,补码与二进制)

在讲移位操作符之前,首先博主得补充些小知识,原码,反码和补码与二进制的相关知识

在日常生活中我们经常能够听到2进制、8进制、10进制、16进制的讲法,那是什么意思呢" />,用1表示"负",而数值位最高位的一位是被当做符号位,剩下的都是数值位。
正整数的原、反、补码都相同
负整数的三种表示方法各不相同
(1):原码:直接将数值按照正负数的形式翻译成⼆进制得到的就是原码。
(2):反码:符号位不变,其他位依次按位取反就可以得到反码。
(3):补码:反码+1就得到补码。
对于无符号数整数来说,没有符号位,所有位均位有效位。

2.2:左移操作符(<<)

移位规则:左边丢弃,右边补0
#define_CRT_SECURE_NO_WARNINGS#include int main(){int m = 7;int n = m << 1;printf("m = %d\n", m);printf("n = %d\n", n);return 0;}

上面这段代码,将变量m左移一位之后然后赋值给n,7是正整数,因此原码,反码,补码相同,且int类型占四个字节,一个字节是8位,因此是32位。
7的补码:0000 0000 0000 0000 0000 0000 0000 0111
左移一位之后的补码:0000 0000 0000 0000 0000 0000 0000 1110
打印的时候,打印的是原码,而正整数的原码反码补码相同,因此此时将左移之后的补码转换为10进制数之后就是14,因此n = 14;


看完上面的例子后,咱们再看一个负整数的例子。
#define_CRT_SECURE_NO_WARNINGS#include int main(){/*-7 原码:10000000000000000000000000000111 反码:11111111111111111111111111111000 补码:11111111111111111111111111111001*/int m = -7;/* * 左移一位之后补码:11111111111111111111111111110010反码:11111111111111111111111111110001原码:10000000000000000000000000001110*/int n = m << 1;printf("m = %d\n", m);printf("n = %d\n", n);return 0;}

此时,我将m赋值为-7,然后左移一位后赋值给n,在之前我们了解过,对于负整数,我们要求出补码,首先对原码取反得到反码,反码再+1得到补码,接着再左移一位(左边丢弃,右边补0)赋值给n,由于在输出打印的时候,是以原码的形式打印的,因此我们还需要求出左移之后的原码,根据计算可得,-7在左移一位之后得到的是-14,因此n的值为-14。

2.2:右移操作符(>>)

移位规则:首先算数右移分两种:
  • 1.逻辑右移:左边用0填充,右边丢弃。
  • 2.算术右移:左边用原该值的符号位进行填充,右边丢弃。

2.2.1:逻辑右移

#define_CRT_SECURE_NO_WARNINGS#include int main(){/*-7 原码:10000000000000000000000000000111 反码:11111111111111111111111111111000 补码:11111111111111111111111111111001*/int m = -7;int n = m >> 1;/*补码:01111111111111111111111111111100反码:01111111111111111111111111111011原码:00000000000000000000000000000100*/printf("m = %d\n", m);printf("n = %d\n", n);return 0;}

如果是按照逻辑右移的方式来进行移位的话,-7在右移一位之后,应该会变成4。

2.2.2:算术右移

#define_CRT_SECURE_NO_WARNINGS#include int main(){/*-7 原码:10000000000000000000000000000111 反码:11111111111111111111111111111000 补码:11111111111111111111111111111001*/int m = -7;int n = m >> 1;/*补码:11111111111111111111111111111100反码:11111111111111111111111111111011原码:10000000000000000000000000000100*/printf("m = %d\n", m);printf("n = %d\n", n);return 0;}

若按照算术右移的方式,在右边补上符号位,左边丢弃,在上面我们讲解过,对于有符号整数,最高位为符号位,0代表正,1代表负,因此-7在进行算术右移的时候应该补1,按照算术右移的方式,-7在算术右移一位之后,应该会变成-4。

通过观察结果可知,博主使用的vs2022在这里采用的是算术右移,因此n的是为-4。

(1)对于移位操作符,不要移动负数位,这个标准是未定义的。
(2)移位操作符的操作数只能是整数

3:位操作符(运算用的是二进制位的补码)

位操作符有三种,分别是
> 按位与--------- &
按位或--------- |
按位异或------ ^

我们分别来看这三个操作符。

3.1:按位与操作符(&)

首先是按位与操作符,按位与操作符用一句话来总结就是**"同时为1则1",**可能家人们对这句话不是特别理解,我们来看一段代码。
#define_CRT_SECURE_NO_WARNINGS#include int main(){int a = 5;int b = -3;int c = a & b;printf("%d\n", c);return 0;}

将5和-3进行按位与操作然后赋值给c,此时c的值为5,那么为什么为5呢" />-3:原码:10000000000000000000000000000011 反码:11111111111111111111111111111100 补码:11111111111111111111111111111101 5:补码:00000000000000000000000000000101 c:补码:00000000000000000000000000000101

将5和-3的补码表示出来后,接下来就要对每一位进行按位与操作,什么叫同时为1则为1呢,譬如在这里,5的二进制位的最高位为0,-3的二进制为的最高位为1,由于不同时为1,那么在进行按位与操作后,因此c的二进制位的最高位得到的是0。再来,5的二进制位的最低位是1,-3的二进制位的最低位也是1,因此c的二进制位的最低位为1。其他的二进制位同样按照这种方式进行计算。在进行计算后,得到c的补码,我们发现最高位是0,因此c是正整数,那么原、反、补码相同,将其二进制转换为十进制得到的就是5。

3.2:按位或操作符(|)

讲完了按位与操作符之后,接下来再讲讲按位或操作符,按位或操作符用一句话总结就是**"其中为1则为1"。**,我们还是来看一段代码。
#define_CRT_SECURE_NO_WARNINGS#include int main(){int a = 5;int b = -3;int c = a | b;printf("%d\n", c);return 0;}

将5和-3进行按位或操作然后赋值给c,此时c的值为-3,那么为什么为-3呢" />-3:原码:10000000000000000000000000000011 反码:11111111111111111111111111111100 补码:11111111111111111111111111111101 5:补码:00000000000000000000000000000101 c:补码:11111111111111111111111111111101 反码:11111111111111111111111111111100 原码:10000000000000000000000000000011

将5和-3的补码表示出来后,接下来就要对每一位进行按位或操作,什么叫其中为1则为1呢?譬如在这里,5的二进制位的最高位为0,-3的二进制为的最高位为1,由于存在1,那么在进行按位或操作后,因此c的二进制位的最高位得到的是1。再来,5的二进制位的最低位是1,-3的二进制位的最低位也是1,因此c的二进制位的最低位为1。其他的二进制位同样按照这种方式进行计算。在进行计算后,得到c的补码,我们发现最高位是1,也就是说此时变量c为负整数,因此我们要求出其原码,补码求出原码的方式:**(1):符号位不变,补码减1得到反码;(2):符号位不变,数值位进行取反得到原码。**得到原码后,将其转换10进制数得到的就是-3啦!

3.3:按位异或操作符(^)

接下来我们再看一个位操作符,按位异或操作符,按位异或操作符用一句话来总结就是"相同为0,相异为1"。我们直接看下面这段代码。
#define_CRT_SECURE_NO_WARNINGS#include int main(){int a = 5;int b = -3;int c = a ^ b;printf("%d\n", c);return 0;}


将5和-3进行按位异或操作然后赋值给c,此时c的值为5,那么为什么为-8呢" />-3:原码:10000000000000000000000000000011 反码:11111111111111111111111111111100 补码:11111111111111111111111111111101 5:补码:00000000000000000000000000000101 c:补码:11111111111111111111111111111000 反码:11111111111111111111111111110111 原码:10000000000000000000000000001000

将5和-3的补码表示出来后,接下来就要对每一位进行按位或操作,什么叫相同为0,相异为1呢?譬如在这里,5的二进制位的最高位为0,-3的二进制为的最高位为1,0和1不是相同的,那么在进行按位异或操作后,因此c的二进制位的最高位得到的是1。再来,5的二进制位的最低位是1,-3的二进制位的最低位也是1;1和1是相同的,因此c的二进制位的最低位为0。其他的二进制位同样按照这种方式进行计算。在进行计算后,得到c的补码,我们发现最高位是1,也就是说此时变量c为负整数,因此我们要求出其原码,得到原码后,将其转换10进制数得到的就是-8啦!

  • a ^ a = 0;
  • 0 ^ a = a;

PS:对于位操作符,他们的操作数也同样必须为整数。

4.赋值操作符

赋值操作符是一个很棒的操作符,他可以让你得到一个你之前不满意的值,也就是你可以给自己重新赋值。
#define_CRT_SECURE_NO_WARNINGS#include int main(){//初始化体重为120int weight = 120;//不满意就赋值weight = 90;return 0;}

4.1:复合赋值符

+=-=*=/=%=>>=<<=&=|=^=
像上面的运算符都可以写成复合的效果,那什么是复合的效果呢,我们来看一段代码。
#define_CRT_SECURE_NO_WARNINGS#include int main(){int a = 10;//等价于 a = a + 1a += 1;int b = 5;//等价于 b = b << 3b <<= 3;printf("%d\n", a);printf("%d\n", b);return 0;}

这段代码中的a += 1等价于 a = a + 1,用变量a最初值进行加1然后再赋值给a;那么同理,b也是一样,b <<= 3 等价于 b = b << 3;将b左移三位以后然后赋值给b。其他的复合操作符也是同理哦,这里博主就不一一举例啦,uu们下去以后可以自己去进行尝试.

5:单目操作符

!逻辑反操作- 负值+正值&取地址sizeof求操作数的数据类型长度(以字节为单位)~对一个数的二进制位取反(操作的是补码)--前置、后置--++前置、后置++*间接访问操作符(解引用操作符)(类型) 强制类型转换

5.1:逻辑反操作符(!)

逻辑反操作符是将true(非0值)转换false(0);将false(0)转换为1(非0值)。这句话是什么意思呢” />#define_CRT_SECURE_NO_WARNINGS#include int main(){int data = 0;int b = !data;printf(“%d\n”, b);if (b){printf(“hello world\n”);}return 0;}

我们定义一个变量data为0,然后对其进行逻辑反操作之后赋值给b,原本data为0,对其进行逻辑反操作后赋值给b,那么此时b为非0值,在之前我们了解过,C语言中非0为真,0为假,因此,此时if的条件判断成立,会在屏幕上打印hello world,同时我们也可以观察b的值是多少。

5.2:正值,负值操作符(+ -)

正值,赋值操作符就是我们在数学中所见到的正负号。

#define_CRT_SECURE_NO_WARNINGS#include int main(){int a = -5;int b = -a;int c = +a;printf("b = %d,c = %d\n", b, c);return 0;}

注意:在C语言中对负数使用正值操作符然后再赋值给其他变量,该变量的值依旧为负数。

5.3:取地址操作符和解引用操作符(& *)

取地址操作符与解引用操作符这里博主就直接通过代码来进行讲解。
#define_CRT_SECURE_NO_WARNINGS#include int main(){int a = 10;//定义指针变量p,存储a的地址int* p = &a;//对p进行解引用操作,*p是通过p中存放的地址,找到所指的对象,*p其实就是a*p = 20;printf("a= %d\n", a);printf("*p = %d\n", *p);printf("p=%p\n", p);return 0;}

这段代码我们定义一个变量a,然后使用&(取地址操作符)取出a的地址赋值给p,在C语言初识时,博主讲过,地址存放指针里头,因此在这里定义了一个指针变量p来存放变量a的地址;然后对指针变量p使用*(解引用操作符)找到其所指的对象,因此 *p 为变量 a

5.4 sizeof操作符

sizeof操作符在之前我们就已经见过了,可以求出变量(数据类型)所占的空间大小。我们直接来看下面这段代码
#define_CRT_SECURE_NO_WARNINGS#include int main(){/*sizeof是计算类型创建变量或者变量的大小,单位为字节sizeof计算的结果是size_t类型的size_t是无符号整型的对size_t类型的数据进行打印,可以使用%zd*/int a = 10;printf("%zd\n", sizeof(a));printf("%zd\n", sizeof(int));printf("%zd\n", sizeof a);return 0;}

sizeof后面的括号在括号中写的不是数据类型的时候,括号可以省略,因此sizeof不是函数sizeof是操作符,单目操作符。

5.5:按位取反操作符(操作的是补码)

什么是按位取反操作符呢?所谓按位取反操作符,就是将一个数的二进制位补码进行取反,对于0取反之后则为1,对于1取反之后则为0,我们来看下面这段代码。
#define_CRT_SECURE_NO_WARNINGS#include int main(){int a = 0;int b = ~a;printf("%d\n", b);return 0;}

0:补码:00000000000000000000000000000000b:补码:11111111111111111111111111111111反码:11111111111111111111111111111110原码:10000000000000000000000000000001

为什么结果是对0按位取反后结果是-1呢” />5.6:++,–操作符

++与--操作符,这里我们直接看代码。
#define_CRT_SECURE_NO_WARNINGS#include int main(){int a = 5;//先使用,后+1int b = ++a;//a = 6;b = 6 printf("前置++后:a = %d,b = %d\n", a,b); b = a++;//b = 6,a = 7printf("后置++后:a = %d,b = %d\n",a,b);return 0;}

前置++的窍门:先+1后使用,在这里,先对a进行+1然后再将其赋值给b,那么此时a的值为6,b的值也为6。
后置++的窍门:先使用再+1,在这里,先将a的值赋值给b,由于前面对a使用一次前置++,使用完了以后a再+1,此时a的值为7,b的值依旧为6
PS:前置++和后置++对要自增的变量的本身没区别

5.7:强制类型转换操作符

所谓强制类型转换,就是将一种数据类型强制转换另外一种数据类型.
#define_CRT_SECURE_NO_WARNINGS#include int main(){//强制类型转换为整型;int a = (int)3.14;printf("%d",a)return 0;}

在这里,我们将a这个double类型的变量使用强制类型转换,那么此时在屏幕上打印的时候,只会打印整数,不遵循四舍五入哦!只保留整数部分。
PS:在C语言中,直接写出浮点数,会被编译器识别为double类型,例如17.0就会被编译器识别为double类型,如果要令其为float类型,则应表示为17.0f。

6:关系操作符

>>=<<=!=用于测试“不相等”==用于测试“相等”
这些关系运算符比较简单,博主就不具体讲解啦,但是要注意一些运算符使用时候的陷阱。

PS:在编程的过程中要注意== 和 =不小心写错而导致的错误哦!

7:逻辑操作符

&& 逻辑与|| 逻辑或

逻辑操作符呢博主在C语言初识那篇博客中详细讲解了概念,这里博主就不再讲解啦,忘记了的uu们可以返回C语言初识那篇博客去看看哦!博主这里就针对这两个操作符的特性来讲解短路操作.我们看下面这两段代码

7.1:逻辑与操作(&&)

#define_CRT_SECURE_NO_WARNINGS#include int main(){int i = 0,a = 0, b = 2, c = 3, d = 4;i = a++ && ++b && d++;printf("a = %d,b = %d, c = %d, d = %d\n", a, b, c, d);printf("i = %d\n", i);return 0;}

为什么这段代码执行出来只有a的值发生变化了呢” />7.2:逻辑或操作(| |)

#define_CRT_SECURE_NO_WARNINGS#include int main(){int i = 0, j, a = 0, b = 2, c = 3, d = 4;j = a++ || ++b || d++;printf("a = %d,b = %d,c = %d,d = %d\n", a, b, c, d);printf("j = %d\n", j);return 0;}

为什么这段代码执行出来a,b,j的值发生变化了呢?原因在于逻辑或操作符也有短路操作的特性,我们在之前讲到过,逻辑或操作是其中为真则为真,由于对变量a使用的是后置++,那么是先使用 a == 0进行判断,此时出现了一个0,因此继续向后判断,对b是使用的是前置++,因此是先使用再++,此时b的值为3,在之前我们讲到过,C语言中,0为假,非0为真,因此由于出现了一个真,那么整个表达式的值为真,就不会再继续向后判断,执行后面的语句了。由于整个表达式的值为真,因此j的值为1,a的值为1,b的值为3,其他变量的值保持不变。

8.条件操作符(三目操作符)

所谓三目操作符,其实和之前所学习到了if else语句一样,只是换汤不换药,万变不离其宗,我们直接看下面这段代码.
表达式1的结果为真,则执行表达式2;且表达式2的结果是整个表达式的结果;表达式3不计算如果表达式1的结果为假,表达式2不计算;则执行表达式3;且表达式3的结果为整个表达式的结果exp1 " />: exp3
#define_CRT_SECURE_NO_WARNINGS#include int main(){int a = 0;int b = 0;int max = 0;scanf("%d %d", &a, &b);max = a > b ? a : b;printf("max = %d\n", max);return 0;}

我在这里用三目操作符来实现两个数找最大值,若a > b 这个表达式成立的话,那么则将a赋值给max,若a > b这个表达式为假,则将b赋值给max.

9:下标引用、函数调用和结构体成员访问操作符

这三个操作符,博主之前在C语言初识那篇博客中详细讲解了,忘了的uu可以回去看看哦.

9.1:下标引用

#define_CRT_SECURE_NO_WARNINGS#include int main(){int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };//[]下标引用操作符printf("%d", arr[0]);return 0;}

9.2:函数调用操作符

()函数调用
接受一个或者多个操作数:第一个操作数为函数名,剩余的操作数就是传递给函数的参数。

#define_CRT_SECURE_NO_WARNINGS#include int Product(int x ,int y){return x * y;}int main(){int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };//()函数调用操作符printf("hello world\n");int a = 0;int b = 0;scanf("%d %d", &a, &b);//()函数调用操作符int value = Product(a, b);printf("%d\n", value);return 0;}

9.3:结构体成员访问

. 结构体变量.成员名
-> 结构体指针变量->成员名

#define_CRT_SECURE_NO_WARNINGS#include struct book{char name[20];intprice;};void Print(struct book * b){//通过*解引用操作,找到所指的对象printf("%s %d\n", (*b).name, (*b).price);//结构体指针变量->成员名printf("%s %d\n", b->name, b->price);}int main(){struct book b = { "C++书籍",25 };//结构体.成员,找到所指的对象printf("%s %d\n", b.name, b.price);Print(&b);return 0;}

10:操作符的属性

C语言操作符有三个重要的属性影响因素
  • 操作符的优先级
  • 操作符的结合性
  • 是否控制求值顺序

10.1优先级

优先级指的是,如果一个表达式包含多个运算符,哪个运算符应该优先执行。各种运算符的优先级是不一样的。

3 + 4 * 5;

上⾯⽰例中,表达式 3 + 4 * 5 ⾥⾯既有加法运算符( + ),⼜有乘法运算符( * )。由于乘法的优先级⾼于加法,所以会先计算 4 * 5 ,⽽不是先计算 3 + 4 。

10.2结合性

如果两个运算符优先级相同,优先级没办法确定先计算哪个了,这时候就看结合性了,则根据运算符是左结合,还是右结合,决定执⾏顺序。大部分运算符是左结合(从左到右执行),少数运算符是右结合(从右到左执行),比如赋值运算符

5 * 6 / 2;

上面示例中,*和/的优先级相同,它们都是左结合运算符,所以从左到右执行,先计算 5 * 6,再计算6 / 2。

上图是C语言操作符的优先级顺序,uu们不需要全部记忆,只需要记住大概就好,在使用的时候如果忘记了查看表格即可!

11:表达式求值

11.1:整型提升

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

11.1.1整型提升的意义:

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

11.1.2:如何进行整型提升

1:有符号整数提升是按照变量的数据类型的符号位来进行提升的.
2:无符号数整型提升,高位补0.

#define_CRT_SECURE_NO_WARNINGS#include int main(){char a = 5;char b = 126;char c = a + b;printf("%d\n", c);return 0;}

5:补码:00000000 00000000 00000000 00000101a:补码:00000101126:补码:00000000 00000000 00000000 01111110b:补码:01111110c:补码:10000011整型提升后c:补码:11111111 11111111 11111111 10000011反码:11111111 11111111 11111111 10000010原码:10000000 00000000 00000000 01111101

上述代码中,将5存放在char类型的变量a中,将126存放在char类型的变量b中,由于char类型只占1个字节即8个bit位,int类型占个4个字节,32个bit位,因此会发生截断,取其前8位存放;那么分别将5和126的补码表示出来,表示出来后,取前8位,分别得到变量a与变量b的补码,最后将其补码相加得到变量c的补码,在打印变量c时,使用的是%d,十进制整数占位符,因此会发生整型提升,那么怎么提升呢?我们已经得到了变量c的补码,char类型的数据是signed char 还是 unsigned char是不确定的,C语言没有明确指定,是取决于编译器的,博主当前使用的VS上,char 类型默认是signed char即有符号数,因此在整型提升时,按照其符号位来进行提升,由于C的符号位为1,因此在整型提升时,进行高位补1,补齐剩下的24个字节,在进行整型提升后,我们得到了补码,由于在打印时打印的是原码,因此我们求出其原码,最后将其转换为10进制的数就能得出c的值为-125。

11.2:算术转换

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

如果某个操作数的类型在上⾯这个列表中排名靠后,那么⾸先要转换为另外⼀个操作数的类型后执⾏运算。

11.3:问题表达式解析

11.3.1:表达式1

a * b + c * d + e * f;

上述表达式在计算的时候,由于*比+的优先级高,只能保证,的计算比+早,但是优先级并不能觉得第三个比第一个+早执行。那么就会如下两种情况的计算顺序。

11.3.2:表达式2

c + --c;

操作符的优先级只能决定自减–的运算在+的运算之前,但是我们并没有办法得知,+操作符的左操作数的获取在右操作数之前还是之后求值,所以结果是不可预测的。

11.3.3:表达式3

#include int fun(){static int count = 1;return ++count;}int main(){int answer;answer = fun() - fun() * fun();printf("%d\n",answer);return 0;}

上述代码虽然在大多数编译器上求得的结果是一样的,但是在表达式answer = fun() – fun() * fun()
中我们只能通过操作符的优先级得知:先算乘法,再算减法,函数的调用顺序无法通过操作符的优先级确定。

好啦,家人们,关于这块的相关细节知识,博主就讲到这里了,如果uu们觉得博主讲的不错的话,请动动你们滴的小手给博主点个赞,你们滴鼓励将成为博主源源不断滴动力!