当前位置: 首页 > news >正文

运算符与表达式

目录

1.运算符

2.表达式

3.运算符的分类

3.1 算术运算符

++(自增运算符)

– – (自减运算符)

3.2 关系运算符

3.3 逻辑运算符

C语言逻辑运算符是 "惰性运算"

3.4 位运算符

1.~ 按位取反

2. & 按位与

3. | 按位或

4. ^ 按位异或

有两个变量 a,b 要交换a和b的值 不适用其他临时变量

5. << 按位左移

6. >> 按位右移

7.掩码(mask)

8.总结

3.5 赋值运算符

赋值表达式的值:就是赋值完之后 左边那个操作数的值

3.6 条件运算符

? : 三目运算符

3.7 逗号运算符

3.8 指针运算符

3.9 求字节运算符

3.10 分量运算符

3.11 下标运算符

3.12 强制类型转换

4.运算符的优先级和结合性


1.运算符

什么是运算符

运算符是用来表示某种运算(操作)的符号

如:+ - * / % 等

根据运算符需要带几个操作数(运算符) 分为

> 单目运算符:该运算符只需要一个操作数 如 : ++ - - &(取地址符) 等

> 双目运算符:该运算符需要两个操作数 如 :+ - * / % 等

> 三目运算符:该运算符需要三个操作数 如: **? :**

结合性:决定先算哪个操作数的问题

从左至右结合 从右至左结合

举个例子

在C语言中 已知 + 的结合性 从左至右

a + b 和 b + a 在C语言中含义不一样的

运算符的优先级

> 在含有多个运算符的表达式中 决定先算哪个运算符 后算哪个运算符

> 如: a + b*c

单目运算符 > 算术运算符 > 关系运算符 > 逻辑运算符 > 赋值运算符 > 逗号运算符

2.表达式

什么是表达式

> 表达某个意思的式子

> C语言中的表达式一般来说是用 运算符连接操作数的式子 如: 3 + 5

表达式的值

> 是一个表达式 就一定会有一个值 这个值就是表达式的值

> 表达式最终需要表达某个意思 某个意思就是表达式的值 3.运算符的分类

3.运算符的分类

3.1 算术运算符

进行算术运算的运算符

++ -- 单目运算符

* / % 双目运算符

+ - 双目运算符

+ - * / 只需要操作数是一个数(整数可以 浮点数可以)

% 取余 要求两个操作数必须是 整数

如:

3 + 4

3.5 + 4.7

3.5 * 6

3.3 / 2

5 % 3

3 % 3.3 error

4 / 2 => 2

5 / 2 => 2

5 / 3 => 1

5 / 2.0 => 2.5

(double)(3/2) => 1.0

(double)3 / 2 => 1.5

++(自增运算符)

自增(+1) 运算符 单目运算符 要求操作必须为一个左值(lvalue)

在C语言中 只有变量才具备左值

  • 前置++: ++在前面 ++x
  • 后置++: ++在后面 x++```

– – (自减运算符)

自减(+1) 运算符 单目运算符 要求操作必须为一个左值(lvalue)

在C语言中 只有变量才具备左值

  • 前置- -: - - 在前面 - - x
  • 后置- -: - -在后面 x- -

表达式的值 做完表达式之后 i 的值

i++ i i = i + 1

++i i+1 i = i + 1

i-- i i = i - 1

--i i-1 i = i - 1

例子: int i = 5; int j = 6; int a; a = (i++) + (i+j);//a=17 或 a = (i+j) + (i++);//a=16

3.2 关系运算符

用来判断两个东西的 关系的运算符 关系:数值大小关系 "比 数值大小"

双目运算符 结合性 从左至右

> < >= <= ==(等于) != (不等于)

关系表达式: 用关系运算符连接起来的表达式 如 a > b

关系表达式的值

  • ​ 关系成立
  • ​ 关系不成立 0

如:

5 > 3 表达式的值是 1

5 > 7 表达式的值是 0

5 >= 5 表达式的值是 1

5 > 4 > 3 表达式的值为 0

结合型 从左至右

==> (5>4) > 3

==> 1 > 3

==> 0

5 > 4 > 3 是一个合法的表达式 是拿 5 > 4 的值 和 3 进行比较

在C语言中 5 > 4 > 3 这个表达式和数学上 "5 > 4 > 3" 的含义是不一样的

(1) C语言中 5 > 4 > 3 <===> (5 > 4) > 3

(2) 数学上 5 > 4 >3 是 "5 > 4" 并且 "4 > 3"

3.3 逻辑运算符

! 逻辑非 单目运算符 "取反"

&& 逻辑与 双目运算符 "并且" 从左至右

|| 逻辑或 双目运算符 "或者" 从左至右

逻辑表达式:用逻辑运算符 (! && ||) 连接起来的式子 称为 逻辑表达式

逻辑表达式的值

  • ​ 真:1
  • ​ 假:0

但是非0 也是逻辑真

a b a&&b a||b

真 真 真 真

真 假 假 真

假 真 假 真

假 假 假 假

例子 int a = 4; int b = 5; a && b ==> 1 a || b ==> 1 !a && b ==> 假 && 真 ==> 0

注意优先级

5 > 3 && 8 < 4 - !0

5 > 3 && 8 < 4 - 1

5 > 3 && 8 < 3

1 && 0 ==> 真 && 假 ==> 假 ==> 所以表达式的值 0

练习

1. 分析如下程序的输出结果 #include <stdio.h> int main() { int a,b,c,d,m,n; a = 1; b = 2; c = 3; d = 4; m = 1; n = 1; (m = a > b) && (n = c > d); printf("%d %d %d %d %d %d\n",a,b,c,d,m,n);//1 2 3 4 0 1 }

C语言逻辑运算符是"惰性运算"

a && b && c

只有当a为真 才需要判断b的值

只有当 a b 都为真 才需要判断 c的值

a || b || c

只要a的值为真 就不需要判断b和c的值

只有 a 和 b都为假 才需要判断 c 的值

总之 如果实现知道了表达式的值啦 那么后面的运算符或表达式就不执行了

练习:

2. 分析如下程序的输出结果 注:&& 的优先级比 || 高 提示:考虑运算符的结合性(从左至右) //优先级不等于求值顺序 优先级只是为了确保正确的分组 求值一定是从左往右 //(group) || (c = c - 1) int a = 0,b = 1,c = 1; int d = a && (b = b - 1) || (c = c - 1); printf("%d %d %d %d\n",a,b,c,d);//0 1 0 0 /* ( a && (b = b - 1) ) || (c = c - 1) x || y 0 || 0 */ //a || (group) int a = 1,b = 1,c = 1; int d = a || (b = b - 1) && (c = c - 1); printf("%d %d %d %d\n",a,b,c,d);//1 1 1 1 /* a || ( (b = b - 1) && (c = c - 1) ) x || y x为1 所以y式子 不执行 */ int a = 0,b = 1,c = 1; int d = a || (b = b - 1) && (c = c - 1); printf("%d %d %d %d\n",a,b,c,d);//0 0 1 0 /* a || ( (b = b - 1) && (c = c - 1) ) x || y x为0 所以y的值会影响整个式子的值 当y为0 整个式子为0 当y为1 整个式子为1 所以 y需要执行 0 || 0 */

3.4 位运算符

位运算符 是 按bit位展开来进行的运算 意思就是说 操作数会展开为 bit位 然后再进行运算

位运算符要求 操作数必须为整数

~ 按位取反

& 按位与

| 按位或

^ 按位异或

<< 按位左移

>> 按位右移

除了 ~(按位取反) 是单目运算符之外 其他所有的都是双目运算符 结合性 从左至右

1.~ 按位取反

1 -> 0 0 -> 1 !3 逻辑非 ==> 0 ~3 (假设 int 占 32bits) 00000000 00000000 00000000 0000 0011 11111111 11111111 11111111 1111 1100 <-- ~3

NOTE:

> 按位取反 ~ 和 逻辑非 !

> 都是单目运算符

  • !x 对于x没有要求
  • ~x 要求x 是整数

练习:

1.分析如下程序的输出结果 #include <stdio.h> int main() { int a = ~(-3); printf("%d\n",a);// 2 printf("%u\n",a);// 2 /* |-3|的原码: 00000000 00000000 00000000 0000 0011 11111111 11111111 11111111 1111 1100 取反 补码: 11111111 11111111 11111111 1111 1101 +1 <-- -3在计算机中的存放形式 ∴ ~(-3) 00000000 00000000 00000000 0000 0010 */ int b = !(-3); printf("%d\n",b);// 0 printf("%u\n",b);// 0 }

2. & 按位与

a & b 双目运算符 结合性:从左至右

aba & b
111
100
010
000

例子:假设int 占 32bits

3 & 5 == 1

00000000 00000000 00000000 0000 0011

& 00000000 00000000 00000000 0000 0101

00000000 00000000 00000000 0000 0001

3 & 7 == 3

00000000 00000000 00000000 0000 0011

& 00000000 00000000 00000000 0000 0111

00000000 00000000 00000000 0000 0011

练习

1.假设有一个整型变量a 我要把a的bit5 变为0 其他bit位保持不变 该如何操作

a = a & 0xFFFFFFDF;

a = a & ~(1<<5) ;

结论:

  • 一个bit位 与 0 进行 "按位与&" 操作 结果为0
  • 一个bit为 与 1 进行 "按位与&" 操作 结果 保留原值

3. | 按位或

a | b 双目运算符 结合性 从左往右

aba|b
111
101
011
000

例子:假设int占 32bits

3 | 5 == 7

00000000 00000000 00000000 0000 0011

| 00000000 00000000 00000000 0000 0101

00000000 00000000 00000000 0000 0111

3 | 7 == 7

00000000 00000000 00000000 0000 0011

| 00000000 00000000 00000000 0000 0111

00000000 00000000 00000000 0000 0111

练习:

1.假设有一个整型变量a 我要把a的bit5 置1 其他bit位保存不变 该如何操作

a = a | 0x00000020;

a = a | (1<<5);

结论

  • 一个bit位 与 1进行 "按位或|"操作 结果为1
  • 一个bit为 与 0进行 "按位或|"操作 结果 保留原值

4. ^ 按位异或

异或:求异 不同为1 相同为0

aba^b
110
101
011
000

例子:假设int占32bits

2^32 == 34

00000000 00000000 00000000 0000 0010

^ 00000000 00000000 00000000 0010 0000

00000000 00000000 00000000 0010 0010

3 ^ 7 == 4

00000000 00000000 00000000 0000 0011

^ 00000000 00000000 00000000 0000 0111

00000000 00000000 00000000 0000 0100

练习

1.假设有一个整型变量a 我要把a的bit5 保持不变 其他位取反 该如何操作

a = a ^ 0xFFFFFFDF;

a = a ^ ~(1<<5);

结论

  • 一个bit位 与0进行 "按位异或"操作 结果保留原值
  • 一个bit位 与1进行 "按位异或"操作 结果 取反
有两个变量 a,b 要交换a和b的值 不使用其他临时变量

> 异或可以实现

a = a ^ b;

b = a ^ b;

a = a ^ b;

证明:

a b a = a ^ b b = a ^ b a = a ^ b

0 0 a=0 b=0 a=0 b=0 a=0 b=0

0 1 a=1 b=1 a=1 b=0 a=1 b=0

1 0 a=1 b=0 a=1 b=1 a=0 b=1

1 1 a=0 b=1 a=0 b=1 a=1 b=1

5. << 按位左移

a << n 双目运算符 结合性 从左至右 "把a按bit位 整体左移n位"

  • 高位左移后 直接丢弃 低位空出来的n位 直接补0
  • 如果丢弃的高位都是0的话 那么左移n位 就表示 乘以 2的n次方
1 << 4 含义 • 1 是int 类型字面量,二进制:00000001(以常见 32 位 int 为例) • << 左移运算符,整体左移 4 位,低位补 0 1 → 二进制 00000001 1 << 4 → 二进制 00010000,十进制 16

练习:

1.构造一个整数(32bits) bit7 和 bit5 为 1 其他bit位 为0 该如何构造

(1 << 5) | (1 << 7)

6. >> 按位右移

x >> n 双目运算符 结合性 从左至右 "把a按bit位整体 右移 n位"

  • 低位右移 直接丢弃 高位补什么
  • 对于无符号数 高位补0
  • 对于有符号数 高位补 符号位

练习:

分析如下程序的输出结果 #include <stdio.h> int main() { int a = -1; a = a >> 31; printf("%d\n",a);// -1 printf("%u\n",a);// 2^32 -1 unsigned int b = -1; b = b >> 31; printf("%d\n",b);//1 printf("%u\n",b);//1 }

7.掩码(mask)

  • 掩码是一种位模式
  • 掩码中为1的bit位 表示我们要选取的bit位集合
  • 通俗来讲 就是表示你对哪些bit位感兴趣

如:

我们要选取 bit0 和 bit1 那么 掩码 0x3

00000000 00000000 00000000 0000 0011

如果 mask = 0xFF 表示我要选取 低八位

00000000 00000000 00000000 1111 1111

例子:

1.假设有一个整型变量 x = 0x345678AB 我要选取x的低八位

低八位的掩码 0xFF

x & ( (1<<8)-1 ) ==> 0xAB

2.假设有一个整型变量x 我想要选取x中的 bit5开始的4个bit位(往高位走) 该如何操作 mask: 00000000 00000000 0000 0001 1110 0000 mask: ( (1<<4) - 1) << 5 注: ( (1<<4) -1 ) : 0xF x & mask xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx & 00000000 00000000 00000001 11100000 00000000 00000000 0000000x xxx00000 --> ( x & ( 0xF << 5 ) ) ( x & ( 0xF << 5 ) ) >> 5

8.总结

清0 : &0

置1 : |1

取反 : ^1

3.5 赋值运算符

a = b 双目运算符 结合性 "从右往左" 把表达式b的值 赋值给 a

赋值运算符的优先级 排倒数第二 倒数第一是逗号运算符

a = b

把表达式b的值 赋值给a(把这个值b写入到a的地址中去a需要具备一个可写的地址(左值) "变量"

赋值符号左边的操作数必须为"可写的地址"

例子

5 = 5 //error 5 == 5 //ok 2 + 3 = 5;//2 + 3 表达式 不具备左值 int x = 2,y = 3; x + y = 5;//error x + y也是表达式 x = 5;//ok x++ = 6; /* 4-赋值运算符.c: In function ‘main’: // 赋值操作的左边需要是一个左值 4-赋值运算符.c:6:9: error: lvalue required as left operand of assignment 6 | x++ = 6; | ^ */

赋值表达式:由赋值运算符连接操作数的式子 称为 赋值表达式

赋值表达式的值:就是赋值完之后 左边那个操作数的值

y = x = 3;

==>

y = (x = 3); //x = 3 是一个赋值表达式这个表达式的值 就是 x的值

把赋值表达式 x = 3 的值 赋值给 y

复合的赋值运算符:赋值运算符可以和算术运算符、位运算符组成复合的赋值运算符

+= -= *= /= %=

>>= <<= |= &= ^=

a += b;//===> a = a + b;

a <<= 2;// ===> a = a << 2;

3.6 条件运算符

? : 三目运算符

expression ? a : b

  • 先判断 expression 的值 如果它的值为真(非0) 则整个表达式的值为 a
  • 如果它的值为假(0) 则整个表达式的值为 b
    if(a > b) { x = 250; } else { x = 360; } x = (a>b?250:360); 或 a>b?(x = 250):(x = 360);

3.7 逗号运算符

a,b 双目运算符 结合性 从左至右 优先级最低

先计算表达式a的值 然后再算 表达式b的值整个逗号表达式的值就是最右边那个表达式的

表达式1,表达式2

例子

a = (3,2) //a的值为 2

这是把表达式 (3,2) 的值 赋值为 a

a = 3,a = 2

a = 3,a = 2,a = 4

=> (a = 3,a = 2),a = 4

逗号表达式的形式可以是下面这样的

表达式1,表达式2,表达式3, …. , 表达式n

  • 求值顺序:先算表达式1 再算表达式2 再算表达式3 …. 最后算表达式n的值
  • 整个逗号表达式的值 就是最右边那个表达式的值

分析如下程序的结果

int main() { int a,b,c,d; int e = (a = 5,b = 6,c = 7,d = 8); printf("%d %d %d %d %d\n",a,b,c,d,e);//5 6 7 8 8 }

3.8 指针运算符

* 指向运算符

& 取地址运算符

3.9 求字节运算符

sizeof()

int a[10];//数组名为a 数组元素个数10个 a[0] ~ a[9] 数组元素的类型 int

sizeof(a[0]): 4 bytes

sizeof(a) : 40 bytes

3.10 分量运算符

.

->

3.11 下标运算符

[]

如:

取数组的元素

a[0]

a[1]

....

3.12 强制类型转换

(类型)表达式=

(int)3.5

(int)(3.2+4.9) ==> 8

(int)3.2 + 4.9 ==> 7.9

4.运算符的优先级和结合性

运算符结合性
() [] -> .从左至右
! ~ ++ -- +(正号) -(负号) *(指向) &(取地址符) sizeof从右至左
*(乘) /(除) %从左至右
+(加) -(减)从左至右
<< >>从左至右
< <= > >=从左至右
== !=从左至右
& 按位与从左至右
^ 按位异或从左至右
| 按位或从左至右
&&从左至右
||从左至右
?:从右至左
= += -= *= /= %= &=从右至左
^= |= <<= >>=从右至左
,从左至右
http://www.cnnetsun.cn/news/3359189.html

相关文章:

  • 工业信号采集:FOD4216光耦与PIC18F25J11的抗干扰方案
  • HybridCLR热更新开发中UnityLinker.exe报错的系统性排查与解决方案
  • 施工企业合同管控工具测评:蓝燕云全生命周期管理能力
  • Visual C++控制台编程实战:CmdTool工具包设计与实现
  • C#贪吃蛇实战:从零到8KB的零分配与Native AOT优化
  • 爬虫监控与告警系统——成功率/延迟/异常监控与Prometheus+Grafana实战
  • Helloagent chapter8 ragmemory
  • gdb调试基础
  • C++封装libpng与SDL2实现轻量PNG图像处理类
  • C盘清理全攻略:从基础操作到进阶技巧,安全释放30G+空间
  • 项目实战:从零构建Java+MySQL图书借阅系统(Swing版)
  • 智能代理技能(Agent Skills)开发指南与技术解析
  • 企业级AI Agent落地:从模型能力到工程体系的跨越
  • 单片机DAY_2
  • L9958与TM4C1294NCZAD电机控制方案解析
  • Chapter 2 The Well: Navigating Parasitics and Performance in CMOS Fabrication
  • Lua C接口封装设计:构建安全高效的C/C++与Lua双向通信桥梁
  • RoPE旋转位置编码原理与工程实践:从数学本质到CUDA优化
  • 本地AI音乐生成实战:为游戏开发打造史诗级战斗配乐
  • Mythos:AI原生安全时代的数字安全分析师
  • 通义灵码(阿里云)配置和streamlit实现小交互聊天界面
  • Unity插件缺失报错全解析:从编译错误到运行时依赖的完整解决方案
  • 压电蜂鸣器驱动方案设计与PIC18LF47K40实现
  • 【Java实习面试算法冲刺】回溯
  • 鸿蒙ArkTS实战:实现任务数据的保存与启动恢复
  • 虚幻引擎资源热更新实战:HotPatcher避坑指南与解决方案
  • ComfyUI中Z-Image-Turbo+ControlNet+Krea2高清修复方案详解
  • Anthropic TAI #200:Mythos能力驱动的价值对齐与分阶段开放实践
  • SHP文件纯前端处理:从上传到下载的完整实战指南
  • AI应用做出来怎么收费?很多人按次或月收费,亏了?这个技能帮你10分钟生成按词元计费方案