C语言---03运算符与表达式

本文详细介绍了C语言中的各种运算符,包括算术运算符、关系运算符、逻辑运算符、条件运算符、赋值运算符、逗号运算符和位运算符,并讲解了它们的用法、结合方向和优先级。此外,还探讨了位运算符的右移分类和逻辑右移与算术右移的区别。最后,提供了运算符优先级的记忆口诀,帮助读者更好地理解和应用C语言中的运算规则。
摘要由CSDN通过智能技术生成

目录

一 运算符

(一) 算术运算符(+,-,*,/,%,++,--)

1、基本算术运算符

2、自增自减运算符

(二) 关系运算符(>,<,>=,<=,==,!=)

(三) 逻辑运算符(&&,||,!)

1、&&(逻辑与)

2、||(逻辑或)

3、!(逻辑非

(四) 条件运算符(?:)

(五) 赋值运算符(=,+=,-=,*=,/=,%=)

1、用于给变量赋值,通常也涉及类型转换

2、常用赋值运算符

(六) 逗号运算符(,)

(七) 位运算符(<<,>>,&,|,~,^)

1、<<(左移运算符)

2、>>(右移运算符)

3、&(按位与)

4、|(按位或)

5、~(按位非)

6、^(按位异或)

7、注意

二 优先级

(一) 说明

(二) 记忆口诀

 三、补充

(一)右移分类

1、逻辑右移

2、算术右移

3、逻辑右移和算术右移是编译器决定,但是我们可以检测

(二)综合案例


一 运算符

  • 运算符的优先级:单目 > 双目 > 三目

  • 运算符的目数:运算符操作数的个数

  • 算术运算符 > 关系运算符 > 逻辑运算符 > 条件运算符 > 赋值运算符 > 逗号运算符

(一) 算术运算符(+,-,*,/,%,++,--)

1、基本算术运算符

  • 结合方向:先左后右

  • %取余,必须为整数(浮点数取余有专用的函数fmod)

  • a/b取整:a、b均为整数;a/b除:表达式中需要有一个浮点型

 printf("%d\n", 5 / 2); // 2 整数相除的结果仍为整数,小数会被舍去
 printf("%d\n", -5 / 2); // -2,取整后向零靠拢
 printf("%f\n", 5.0 / 2); // 浮点数与整数相除结果为浮点数,float型数据按double型数据处理

2、自增自减运算符

  • 单目运算符

  • 结合方向:先右后左

  • 后置++/--比前置++/--的优先级要高,前置++/--的运算效率高

  • i++ 或 ++i 作为单独的指令时没有区别

 int a = -1,b = 10,c;
 // 前置++/--和后置++/--的区别
 c = a++; // 后置++:先使用a的值-1赋值给c,c=-1,然后a再自增1,a=0
 printf("a=%d c=%d\n", a, c);
 c = ++b; // 前置++:先b自增1,b=11,然后再将b的值赋值给c,c=11
 printf("b=%d c=%d\n", b, c);

(二) 关系运算符(>,<,>=,<=,==,!=)

  • 运算的结果为逻辑值(逻辑真、逻辑假)

  • 结合方向:从左至右

 printf("%d\n", 1 > 2); // 1是否大于2?不大于,结果为假(0)
 printf("%d\n", 1 != 2); // 1不等于2? 1是不等于2,结果为真(非0值/1)
 printf("%d\n", 1 <= 2); // 1小于等于2?1是小于等于2,结果为真(非0值/1)
  printf("%d\n", 1 == 2); // 1等于2?1不等于2,结果为假(0)
 printf("%d\n", 2 == 2.0); // 2 == 2.0为关系表达式
 int a = 1, b = 2, c = 3;
 printf("%d\n", a == b); // a等于b? a不等于b,结果为假(0)
 printf("%d\n", a+1 == b); // a等于b? a+1等于b,结果为真(非0值/1)
  • 注意:将=右边看成一个整体

 int data = 3;
 // 将=右边看成一个整体
 data *= 3+5; // data = data * (3+5);
 printf("data = %d\n",data); // 24

 // 判断c大于b大于a,关系表达式怎么写
 printf("%d\n", c > b > a);
 // 先算c>b,c的确大于b,结果为逻辑真(非0值/1),再算1>a,1是不大于a,结果为逻辑假(0)
 c > b && b > a; // 再多个条件连续比较时,需要用到逻辑运算符作为连接

(三) 逻辑运算符(&&,||,!)

  • 用于判断表达式的逻辑值,C语言中0为假,其他都为真

1、&&(逻辑与)

  • 判断运算符两边的表达式是否同时为真,同真为真,否则为假

  • &&的短路特性:A&&B,如果A为假,则系统不会执行B

 int num=10;
 printf("比较之前num = %d\n",num);
 
 (2>3) && (num=100); // 这里并没有执行
 printf("比较之后num = %d\n",num);
  • 运行结果:比较之前 = 10,比较之后 = 10

2、||(逻辑或)

  • 判断运算符两边的表达式是否有一个为真,有真为真,否则为假
  • ||的短路特性:A||B,只要A为真,系统不会判断B的真假
 int num=10;
 printf("比较之前num = %d\n",num); // 10
 
 (3>2) || (num=100); // num=100得不到执行
 printf("比较之后num = %d\n",num); // 10

 3、!(逻辑非

  • 真变假,假变真
  • 优先级:!— 算数 — 关系 — && — || — 赋值(!最高)

(四) 条件运算符(?:)

  • ?:(C语言中唯一一个三目运算符)

  • 条件运算符的基本格式:表达式1?表达式2:表达式3

  • 条件运算符的运算规则:首先判断表达式1结果的逻辑值,如果结果为逻辑真则执行表达式2,如果结果为逻辑假则执行表达式3,整个条件表达式为其所执行的表达式的值

 (1 < 2) ? printf("小于\n") : printf("不小于\n"); // 小于
 (1 > 2) ? printf("小于\n") : printf("大于\n"); // 大于
 int a = 10, b = 20, c;
 c = a >= b ? a : b; // 用于求两个数中的最大值
 //  a >= b ? a : b为条件表达式
 printf("%d\n", c); // 20
 printf("我这里有1万元和一个女朋友,请问你要哪个?\n");
 printf("1、我要1万元\n");
 printf("2、我要女朋友\n");
 int n; // 你的选择
 scanf("%d", &n); // 输入你的选择
     n == 1 ? printf("我要1万元\n") :
         (n == 2) ? printf("我要女朋友\n") : printf("小孩子才做选择,大人我全都要!\n"); // 条件运算符的嵌套(?:(?:)),可以理解成为套娃
 // 禁止套娃

(五) 赋值运算符(=,+=,-=,*=,/=,%=)

1、用于给变量赋值,通常也涉及类型转换

  • 浮点型(float、double)赋值给整型,保留整数

  • 整型赋值给浮点型,数值不变,以指数形式存储

  • double型赋值给float型,注意数值范围不要溢出

  • 字符型赋值给整型,ASCII码值给了整型

  • int、short、long赋值给char型,低八位传到char型数据 289 00000001 00100001 相当于把00100001传给char型数据变量

  • 有符号变量传给无符号变量,照搬照抄

  • 不同类型的整型数据传输按照存储单元中的存储形式直接传送

2、常用赋值运算符

  • 结合方向:从右到左

 int x = 100; // 定义了一个int整型变量x,并初始化赋值为100
 x += 10; // x = x + 10; x = 100 + 10 = 110
 x *= 10; // x = x * 10 = 100 * 10 = 1000
 x %= 10; // x = x % 10 = 100 % 10 = 0
 printf("x=%d\n", x);

(六) 逗号运算符(,)

  • 一般起到分隔作用

 int data1 = 0;
 int data2 = 0;
 data1 = 3,4,5,6; // 等号与3结合
 data2 = (3,4,5,6); // 先进行括号里面的操作,最后6与等号结合
 printf("data1 = %d\n",data1); // 3
 printf("data2 = %d\n",data2); // 6
  • 逗号表达式

 int a[3][2]={(1,2),(3,4),(5,6)}; // 2,4
 int a[2][3]={(1,2),(3,4),(5,6)}; // 2,4,6

(七) 位运算符(<<,>>,&,|,~,^)

  • 对数据的二进制形式进行运算符

1、<<(左移运算符)

  • 基本格式:数据<<移动位数

  • 注意:移动的位数不要超过自身长度

  • 左移运算符每移动一位相当于将一个数据乘以2

 printf("%d\n", 1 << 1); // 结果为2
 // 将数据1左移1个二进制位,右边补0
 // 1的二进制为:00000000 00000000 00000000 00000001
 // 1左移1位后为:00000000 00000000 00000000 00000010 = 2
 printf("%d\n", 1 << 2);
 // 1左移2位后为:00000000 00000000 00000000 00000100 = 4

2、>>(右移运算符)

  • 基本格式:数据>>移动位数

// 将一个数据的二进制右移多少位,左边补符号位,符号位不变(算术右移)
printf("%d\n", 8 >> 2); // 结果为2
// 右移运算符每移动一位相当于将一个数据除以2
printf("%d\n", 7 >> 2); // 结果为1
// 7的二进制为:0000 0111
// 7右移2位后为:0000 0001 = 1
printf("%d\n", -7 >> 2); // 结果为-2
// 计算机中数据的表示和运算都是以二进制补码进行的
// -7的原码为:1000 0111
// -7的反码为:1111 1000
// -7的补码为:1111 1001  
// -7的补码右移两位为:1111 1110 
// -7的补码右移两位后再取反+1还原成原码 1000 0001 1000 0010 = -2

3、&(按位与)

  • 双目运算符

  • 运算规则:两个数据相与,各个二进制位分别做与运算,同真为真,否则为假

  • 特点:和1相与,保持不变;和0相与,清零

  • 应用场景:将固定位清零

 printf("%d\n", 1 & 2); // 0
 // 1的二进制:0000 0001
 // 2的二进制:0000 0010
 // 1&2二进制: 0000 0000

4、|(按位或)

  • 双目运算符

  • 运算规则:两个数据相或,各个二进制位分别做或运算,有真为真,否则为假

  • 特点:和0相或,保持不变;和1相或,置1

  • 应用场景:将固定位置1

 printf("%d\n", 1 | 2); // 3
 // 1的二进制:0000 0001
 // 2的二进制:0000 0010
 // 1&2二进制: 0000 0011

5、~(按位非)

  • 单目运算符,按位取反

 printf("%d\n", ~1); // -2
 // 1的二进制:0000 0001(补码)
 // ~1的二进制:1111 1110(补)->1000 0001(反)->1000 0010(原)
 // 这里的负数已经是补码的形式

6、^(按位异或)

  • 两个数据相异或,各个二进制位分别做异或运算,相同为0,相异为1

  • 特点:和0异或,保持不变;和1异或,取反

  • 应用场景:将固定的位发生高低电平翻转

 printf("%d\n", 1^2); // 3
 // 1的二进制:0000 0001
 // 2的二进制:0000 0010
 // 1^2的二进制:0000 0011 = 3
  • 案例:将1010 1010 的第0位发生翻转
  1010 1010
^ 0000 0001
-------------
  1010 1011 // 低电平转换为高电平
^ 0000 0001
-------------
  1010 1010

7、注意

  • 比如我自己输入-1,那么这是原码,要转换成补码再操作

  • 对负数的补码进行按位操作后再还原成原码读取

  • 正数的补码、原码、反码一致

二 优先级

(一) 说明

  • 优先级高先执行,同级别的优先级要看结合性

  • 运算符优先级:初等运算符>单目运算符>算术运算符>关系运算符>逻辑运算符>条件运算符>赋值运算符>逗号运算符

(二) 记忆口诀

口诀解释
初等单目一二级初等运算符、单目运算符为1、2级
乘除求余加减移算术运算符、移位
关系等于不等于关系运算符(< <= > >=)
按位与来异或或位运算符(& ^ |)
逻辑与或条件弱逻辑运算符(&& ||)、条件运算符
赋值逗号一点破赋值、逗号最低

 三、补充

(一)右移分类

1、逻辑右移

  • 右边丢弃,左边补0

2、算术右移

  • 无符号数:右边丢弃,左边补0
  • 有符号数:右边丢弃,左边补符号位(正数补0,负数补1)

3、逻辑右移和算术右移是编译器决定,但是我们可以检测

(二)综合案例

  • 将data的第1、5清0,第3、4位置1,其他位保持不变
unsigned char data = 0xaa; // 1010 1010
  • 将data的第1、5位清0
data = data & 1101 1101;
1101 1101 = ~(0010 0010) =~(0010 0000 | 00000010)
0010 0000 = 0000 0001 << 5
0000 0010 = 0000 0001 << 1
1101 1101 = ~(0x01 <<5 | 0x01<<1)
data = data & ~(0x01<<5 | 0x01<<1);
  • 将data的第3、4位置1
data = data | 0001 1000;
0001 1000 = 0001 0000 | 0000 1000 = 0x01<<4 | 0x01<<3
data = data | (0x01<<4 | 0x01<<3);

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

盾山狂热粉

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值