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

操作符详解:从入门到精通

操作符详解:从入门到精通

前言

操作符是C语言的灵魂,掌握好操作符的使用,就能写出更加高效、优雅的代码。本文将全面系统地讲解C语言中的各类操作符,包括它们的分类、使用方法和注意事项,帮助你彻底搞懂操作符的方方面面。

1. 操作符的分类

C语言中的操作符非常丰富,大致可以分为以下几类:

类别操作符
算术操作符+-*/%
移位操作符<<>>
位操作符&`
赋值操作符=+=-=*=/=%=<<=>>=&=`
单目操作符!++--&*+-~sizeof(类型)
关系操作符>>=<<===!=
逻辑操作符&&`
条件操作符?:
逗号表达式,
下标引用[]
函数调用()
结构成员访问.->

今天我们将重点介绍与二进制相关的操作符(移位、位操作符),以及其他尚未详细讲解的操作符。

2. 二进制与进制转换

在深入位操作符之前,我们需要先了解二进制的基础知识。

2.1 什么是进制?

2进制、8进制、10进制、16进制只是数值的不同表示形式。比如数值15:

  • 2进制:1111
  • 8进制:17(以0开头)
  • 10进制:15
  • 16进制:F(以0x开头)

2.2 2进制转10进制

2进制每一位都有权重,从右向左依次是:(2^0, 2^1, 2^2, \ldots)

例如:二进制1101= (1 \times 8 + 1 \times 4 + 0 \times 2 + 1 \times 1 = 13)

2.3 10进制转2进制

使用除2取余法,不断除以2,将余数从下往上排列。

例如:125转换为2进制 →1111101

2.4 2进制转8进制和16进制

  • 转8进制:从右向左每3位一组,转换为对应的8进制数字(最高位不足3位时直接转换)
  • 转16进制:从右向左每4位一组,转换为对应的16进制数字

💡 小贴士:8进制数以0开头,16进制数以0x开头。

3. 原码、反码、补码

整数的二进制表示有三种形式:原码、反码、补码

3.1 基本规则

类型符号位正数负数
原码最高位,0正1负同原码数值位不变
反码不变同原码符号位不变,数值位取反
补码不变同原码反码+1

重要:整数在内存中存储的是补码

3.2 为什么用补码?

  • 符号位和数值位可以统一处理
  • 加法和减法可以统一处理(CPU只有加法器)
  • 补码与原码的转换过程相同,不需要额外硬件

4. 移位操作符

移位操作符的操作数只能是整数

4.1 左移操作符<<

规则:左边抛弃,右边补0

intnum=10;// 二进制:1010intn=num<<1;// 结果:10100 = 20

4.2 右移操作符>>

右移分为两种:

类型规则
逻辑右移左边补0,右边丢弃
算术右移左边补符号位,右边丢弃

⚠️警告:不要移动负数位,如num >> -1是未定义行为!

5. 位操作符:&、|、^、~

位操作符的操作数必须是整数

操作符名称规则
&按位与对应位都是1,结果为1
``按位或
^按位异或对应位不同,结果为1
~按位取反0变1,1变0
intnum1=-3;intnum2=5;printf("%d\n",num1&num2);// 按位与printf("%d\n",num1|num2);// 按位或printf("%d\n",num1^num2);// 按位异或printf("%d\n",~0);// 按位取反

5.1 经典面试题:不创建临时变量交换两个整数

inta=10,b=20;a=a^b;b=a^b;// b = (a ^ b) ^ b = aa=a^b;// a = (a ^ b) ^ a = bprintf("a = %d, b = %d\n",a,b);

原理:异或运算满足自反性:(a ^ b) ^ b = a

5.2 练习1:求二进制中1的个数

方法1(有缺陷,不能处理负数):

while(num){if(num%2==1)count++;num/=2;}

方法2(循环32次):

for(i=0;i<32;i++){if(num&(1<<i))count++;}

方法3(最优解):

while(num){count++;num=num&(num-1);// 每次消去最右边的1}

💡num & (num - 1)这个技巧非常经典,可以快速消去二进制中最右边的1。

5.3 练习2:二进制位置0或置1

将13的第5位(从0开始计数)修改为1,再改回0:

inta=13;// 第5位置为1a=a|(1<<4);// 第5位置为0a=a&~(1<<4);

6. 单目操作符

单目操作符的特点是只有一个操作数

操作符名称说明
!逻辑反真变假,假变真
++自增前置或后置
--自减前置或后置
&取地址获取变量的地址
*解引用通过地址访问变量
+正号正数
-负号负数
~按位取反二进制位取反
sizeof取大小计算类型或变量的大小
(类型)强制类型转换转换数据类型

7. 逗号表达式

逗号表达式从左向右依次执行,整个表达式的结果是最后一个表达式的结果

inta=1,b=2;intc=(a>b,a=b+10,a,b=a+1);// c的结果是 b = a + 1 = 13// 实用场景:简化while循环while(a=get_val(),count_val(a),a>0){// 业务处理}

8. 下标访问与函数调用

8.1 下标引用操作符[]

操作数:数组名 + 索引值

intarr[10];// 创建数组arr[9]=10;// [] 的操作数是 arr 和 9

8.2 函数调用操作符()

操作数:函数名 + 传递给函数的参数

test1();// () 的操作数是 test1test2("hello");// () 的操作数是 test2 和 "hello"

9. 结构成员访问操作符

9.1 结构体声明

structStu{charname[20];// 名字intage;// 年龄charsex[5];// 性别charid[20];// 学号};

9.2 直接访问:.

structStus={"张三",20};printf("%s %d\n",s.name,s.age);

9.3 间接访问:->

structStu*ptr=&s;ptr->age=21;// 等价于 (*ptr).age = 21

10. 操作符的优先级与结合性

10.1 优先级

优先级决定哪个运算符先执行。乘法优先级高于加法:

3+4*5;// 先算 4*5=20,再加3得23

10.2 结合性

当优先级相同时,结合性决定执行顺序:

  • 左结合:从左到右执行(大部分运算符)
  • 右结合:从右到左执行(赋值运算符等)
5*6/2;// 左结合,先算5*6=30,再除以2得15

10.3 常用优先级速查表

优先级运算符结合性
1(最高)()[].->左到右
2++--&*+-~!sizeof右到左
3*/%左到右
4+-左到右
5<<>>左到右
6<<=>>=左到右
7==!=左到右
8&左到右
9^左到右
10``
11&&左到右
12`
13?:右到左
14=及复合赋值右到左
15(最低),左到右

💡建议:记不住优先级没关系,使用圆括号()明确表达式的计算顺序即可!

11. 表达式求值的陷阱

11.1 整型提升

C语言中,charshort等类型在进行算术运算时,会先转换为intunsigned int,这就是整型提升

提升规则

  • 有符号数:按符号位提升
  • 无符号数:高位补0
chara,b,c;a=b+c;// b和c先提升为int,计算后再截断存入a

11.2 算术转换

当操作数类型不同时,会进行算术转换,向更高精度转换:

long double > double > float > unsigned long > long > unsigned int > int

11.3 问题表达式

有些表达式虽然语法正确,但计算结果不确定,应避免写出:

// 问题1:操作数的求值顺序不确定a*b+c*d+e*f;// 问题2:i的修改和读取顺序不确定c+--c;// 问题3:函数调用顺序不确定fun()-fun()*fun();// 问题4:不同编译器结果不同intret=(++i)+(++i)+(++i);

⚠️核心原则:不要写出过于复杂的表达式,保持代码清晰、可读性强!

总结

本文全面介绍了C语言中的各类操作符,包括:

  1. 进制转换:理解二进制、八进制、十六进制
  2. 原反补码:理解整数在内存中的存储
  3. 移位和位操作:高效处理二进制位
  4. 优先级与结合性:理解表达式求值顺序
  5. 常见陷阱:避免写出有歧义的表达式

掌握好这些知识,你就能写出更加高效、准确的C语言代码。记住:简单清晰的代码比巧妙的代码更有价值


如果觉得这篇文章对你有帮助,欢迎点赞、收藏、分享!

http://www.jsqmd.com/news/916058/

相关文章:

  • ESP32-S3触摸屏开发板实战:从LVGL环境搭建到HID音量控制
  • 海洋环境下 RTK 飞控的厘米级定位原理与抗干扰设计
  • Lindy效应如何重塑你的分析工作流:7个被90%团队忽略的自动化关键节点
  • 魔兽争霸3终极优化指南:如何用免费开源工具解决现代系统兼容性问题
  • 【2026最新】大厂Java面试题+答案(牛客网整理),刷完拿Offer
  • 中国财政科学研究院考研辅导班强烈推荐【独峰考研】全解析 - michalwang
  • 无线通信系统设计:如何根据场景在ZF、MMSE、ML、MRC中做出选择?
  • HarmonyOS StrUtil 字符串判空三兄弟:isNull、isEmpty、isBlank 到底有啥区别?
  • 深度拆解:KTV如何用“免费送酒“策略撬动370万投资
  • 为什么Sunshine游戏串流服务器能让你的游戏体验提升300%?终极跨平台游戏流媒体完整指南
  • 从客户分群到异常检测:轮廓系数在实际业务场景中的高级用法与避坑指南
  • PolicyBank:让LLM智能体从错误中进化,精准理解业务规则
  • claude-code命令之使用国产大模型教程
  • 从零上手Juniper SRX300防火墙:手把手配置DHCP、NTP和Web管理(含安全策略)
  • UWB高精度测距实战:基于RYUW122_Lite模块的AT命令快速上手
  • 验收驱动提示词:让企业 AI 输出可控、可复用
  • 子查询入门|标量 / 行 / 列子查询,简化复杂查询
  • 预订劫持钓鱼风暴深度解析:350家酒店沦陷背后的数据武器化与AI攻击革命
  • HBase Java API实战:从Shell到代码,手把手教你完成增删改查(附完整项目源码)
  • 隐私至上:本地化Cookie导出工具Get cookies.txt LOCALLY完全指南
  • 仿真科普 | 低空经济的“数字风盾”:CFD+数字孪生构建智慧风场仿真体系
  • 别再只盯着路由模式了!天融信防火墙透明模式部署实战,零感知保护内网安全
  • Java 程序员第 40 阶段05:从零搭建 Java 大模型完整项目,接口层设计与API开发
  • HarmonyOS StrUtil 字符串处理实战:trim 去空格、replace 替换、大小写转换全攻略
  • 安川焊接机器人保护气智能节气阀
  • 不只是apt install:手把手教你从官方快照源为Debian 9/10/11安装特定旧版内核
  • GIST框架:基于语义拓扑的轻量化室内空间感知与导航实践
  • 从规则引擎到情境感知:构建个性化内容治理系统的技术实践
  • 如何用SMUDebugTool深度掌控你的AMD Ryzen处理器:新手快速入门指南
  • 别再傻傻分不清了!TPM、TCM、TPCM,这些电脑里的“安全卫士”到底有啥区别?