C语言操作符详解:从基础到进阶

在C语言中,操作符是构建表达式的基础,掌握各类操作符的用法、优先级及特性,对写出高效且正确的代码至关重要。本文将系统梳理C语言操作符的核心知识点,包含实例代码与详细解析,助你彻底搞懂操作符。

1. 操作符的分类

C语言操作符可按功能分为以下几类,清晰的分类有助于理解其特性:

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

2. 二进制与进制转换

计算机底层使用二进制存储数据,掌握进制转换是理解位操作的基础。

2.1 二进制与十进制转换

  • 二进制转十进制:按权重展开求和(权重为20,21,22,...2^0, 2^1, 2^2,...20,21,22,...,从右向左)。
    例:二进制1101转十进制:
    1×23+1×22+0×21+1×20=8+4+0+1=131×2^3 + 1×2^2 + 0×2^1 + 1×2^0 = 8 + 4 + 0 + 1 = 131×23+1×22+0×21+1×20=8+4+0+1=13

  • 十进制转二进制:除2取余,余数倒序排列。
    例:十进制125转二进制:
    125 ÷ 2 = 62 余1
    62 ÷ 2 = 31 余0
    31 ÷ 2 = 15 余1
    15 ÷ 2 = 7 余1
    7 ÷ 2 = 3 余1
    3 ÷ 2 = 1 余1
    1 ÷ 2 = 0 余1
    结果:1111101

2.2 二进制与八/十六进制转换

  • 二进制转八进制:从右向左每3位一组,不足补0,每组对应1个八进制数(0-7)。
    例:二进制01101011 → 分组01 101 011 → 转换为八进制153(前缀0表示八进制)。

  • 二进制转十六进制:从右向左每4位一组,不足补0,每组对应1个十六进制数(0-9, a-f)。
    例:二进制01101011 → 分组0110 1011 → 转换为十六进制0x6b(前缀0x表示十六进制)。

3. 原码、反码、补码

整数在内存中以补码存储,原因是:统一符号位与数值位处理,简化加法运算(CPU仅需加法器)。

  • 原码:直接表示符号位(0正1负)和数值位。
    例:int a = 3 → 原码00000000 00000000 00000000 00000011
    int b = -3 → 原码10000000 00000000 00000000 00000011

  • 反码:原码符号位不变,数值位取反。
    例:-3的反码11111111 11111111 11111111 11111100

  • 补码:反码+1(负数补码);正数原码=反码=补码。
    例:-3的补码11111111 11111111 11111111 11111101

4. 移位操作符

移位操作符仅作用于整数,分为左移和右移。

4.1 左移操作符 <<

  • 规则:左边丢弃,右边补0。
  • 示例
#include <stdio.h>
int main() {int num = 10; // 二进制:00000000 00000000 00000000 00001010int n = num << 1; // 左移1位:00000000 00000000 00000000 00010100 → 20printf("n = %d\n", n); // 输出:20printf("num = %d\n", num); // 输出:10(原变量不变)return 0;
}

4.2 右移操作符 >>

  • 逻辑右移:左边补0,右边丢弃(无符号数)。
  • 算术右移:左边补符号位,右边丢弃(有符号数,主流编译器采用)。

示例(算术右移):

#include <stdio.h>
int main() {int num = -1; // 补码:11111111 11111111 11111111 11111111int n = num >> 1; // 算术右移1位:11111111 11111111 11111111 11111111 → 仍为-1printf("n = %d\n", n); // 输出:-1return 0;
}

⚠️ 注意:禁止移动负数位(如num >> -1,行为未定义)。

5. 位操作符

位操作符直接对二进制位进行操作,操作数为整数。

操作符功能示例(二进制)
`&`按位与(同1则1)1010 & 0111 = 0010
`|`按位或(有1则1)1010 | 0111 = 1111
`^`按位异或(不同则1)1010 ^ 0111 = 1101
`~`按位取反(0变1,1变0)~1010 = 0101(假设4位)
|

经典案例

  1. 不创建临时变量交换两数
#include <stdio.h>
int main() {int a = 10, b = 20;a = a ^ b; // a = 10^20b = a ^ b; // b = (10^20)^20 = 10a = a ^ b; // a = (10^20)^10 = 20printf("a = %d, b = %d\n", a, b); // 输出:a=20, b=10return 0;
}
  1. 求二进制中1的个数
// 方法3(最优):每次消去最后一个1,循环次数=1的个数
#include <stdio.h>
int count_one(int num) {int count = 0;while (num) {num &= num - 1; // 消去最后一个1count++;}return count;
}
int main() {printf("%d\n", count_one(10)); // 1010 → 2个1 → 输出2return 0;
}

6. 单目操作符

单目操作符仅需一个操作数,重点如下:

操作符功能示例
!逻辑非(真变假,假变真)!0 = 1!5 = 0
++自增(前置先增后用,后置先用后增)int a=3; printf("%d", ++a); // 4
--自减(类似++)int a=3; printf("%d", a--); // 3
sizeof求类型/变量所占字节数sizeof(int) = 4sizeof(a) = 4(a为int)
(类型)强制类型转换(int)3.14 = 3

7. 逗号表达式

形式:exp1, exp2, ..., expN

  • 执行顺序:从左到右依次执行。
  • 结果:最后一个表达式的值。

示例:

#include <stdio.h>
int main() {int a = 1, b = 2;int c = (a > b, a = b + 10, a, b = a + 1); // 执行:a>b(假)→ a=12 → 取a=12 → b=13 → 结果c=13printf("c = %d\n", c); // 输出:13return 0;
}

8. 下标访问与函数调用

  • 下标访问[]:操作数为数组名+索引,如arr[3]等价于*(arr+3)

    int arr[5] = {1,2,3,4,5};
    printf("%d\n", arr[2]); // 输出:3(访问第3个元素)
    
  • 函数调用():操作数为函数名+参数列表。

    #include <stdio.h>
    void print_hello() {printf("Hello, C!\n");
    }
    int add(int a, int b) {return a + b;
    }
    int main() {print_hello(); // 函数调用,无参数printf("3+5 = %d\n", add(3, 5)); // 函数调用,有参数 → 输出8return 0;
    }
    

9. 结构体成员访问

结构体成员访问有两种方式:

  • .:直接访问(结构体变量)。
  • ->:间接访问(结构体指针)。

示例:

#include <stdio.h>
#include <string.h>// 定义学生结构体
struct Stu {char name[20];int age;
};int main() {struct Stu s = {"张三", 20}; // 结构体变量struct Stu* ps = &s; // 结构体指针// 访问成员printf("name: %s, age: %d\n", s.name, s.age); // .访问 → 张三, 20strcpy(ps->name, "李四"); // ->访问:修改姓名ps->age = 22; // ->访问:修改年龄printf("name: %s, age: %d\n", s.name, s.age); // 李四, 22return 0;
}

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

表达式求值由优先级和结合性决定:

  • 优先级:决定操作顺序(如*优先级高于+)。
    例:3 + 4 * 5 → 先算4*5=20,再算3+20=23

  • 结合性:优先级相同时,左结合(从左到右)或右结合(从右到左,如赋值=)。
    例:5 * 6 / 2 → 左结合,先算5*6=30,再算30/2=15

优先级简表(从高到低)

优先级操作符结合性
1()[].->左结合
2++--!~sizeof右结合
3*/%左结合
4+-(算术)左结合
5<<>>左结合
6<><=>=左结合
7==!=左结合
8&左结合
9^左结合
10``
11&&左结合
12`
13? :右结合
14=+=-=右结合

11. 表达式求值注意事项

11.1 整型提升

长度小于int的整型(如charshort)在运算时会提升为intunsigned int,避免精度丢失。
例:char a = 127, b = 1; int c = a + b;

  • a提升为00000000 00000000 00000000 01111111
  • b提升为00000000 00000000 00000000 00000001
  • 相加后c = 128(若直接存char会溢出)。

11.2 避免歧义表达式

部分表达式因优先级/结合性无法确定唯一执行顺序,结果依赖编译器,应避免:

  • c + --c:无法确定+左右操作数的求值顺序。
  • (++i) + (++i) + (++i):不同编译器结果不同(如GCC输出10,VS输出12)。

总结

操作符是C语言的基础,掌握其分类、特性及求值规则,能帮助我们写出更高效、无歧义的代码。重点关注位操作符的灵活应用(如交换变量、统计1的个数)、补码的存储逻辑,以及优先级对表达式的影响。实际开发中,复杂表达式建议用括号明确顺序,减少歧义。

希望本文对你理解C语言操作符有帮助,欢迎留言交流! 😊

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/web/90898.shtml
繁体地址,请注明出处:http://hk.pswp.cn/web/90898.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

鸿蒙平台运行Lua脚本

1. 目标 使用 rust 在移动端实现 Lua 脚本的运行。 2. 核心步骤 [Rust Host App]│├── [mLua VM] (通过 mlua 或 rlua 库嵌入)│ ├── 独立Lua状态&#xff08;隔离执行&#xff09;│ ├── 受限标准库&#xff08;禁用危险函数&#xff09;│ └── 内存/CPU限…

【Ubuntu】发展历程

Ubuntu 是一个基于 Debian 的 Linux 发行版&#xff0c;由 Canonical 公司开发和维护。它以其易用性、稳定性和强大的社区支持而著称。以下是 Ubuntu 从发布以来的主要版本和发展历程&#xff1a;1. Ubuntu 4.10 "Warty Warthog" (2004)发布日期&#xff1a;2004年10…

k8s下springboot-admin 监控服务部署,客户端接入

踩坑及解决以下问题 1、客户端监控信息不显示,需要暴露监控检查接口路径 2、服务端不显示客户端日志,需要启用日志,并指定日志路径 3、解决在k8s下,客户端多实例注册id相同,如2个实例只显示一个 整体架构 springboot-admin 由服务端和客户端组成 服务端负责 1、提供 We…

git删除远程分支和本地分支

1. git删除远程分支 git push origin --delete [branch_name]2. 删除本地分支 2.1 git branch -d 会在删除前检查merge状态&#xff08;其与上游分支或者与head&#xff09;。 git branch -d [branch_name] 2.2 git branch -D 直接删除 git branch -D 是 git branch --delete…

Go 的时间包:理解单调时间与挂钟时间

Go 的时间包&#xff1a;理解单调时间与挂钟时间 &#x1f4c5; 引言 Go 语言自版本 1.9 起在 time.Time 中同时支持 “挂钟时间&#xff08;wall‑clock&#xff09;” 和 “单调时间&#xff08;monotonic clock&#xff09;”&#xff0c;用于分别满足时间戳与时间间隔测量…

Android启动时间优化大全

1 修改Android mksh默认的列长度 不修改这个参数&#xff0c;adb shell后&#xff0c;输入超过80个字符&#xff0c;就不能看到完整的命令行。external/mksh/src/sh.h EXTERN mksh_ari_t x_cols E_INIT(80); EXTERN mksh_ari_t x_lins E_INIT(24);2 Kernel优化 2.1 内核驱动模块…

matplotlib.pyplot: 底层原理简析与进阶技巧

文章目录 1 底层实现原理 1.1 核心架构 1.1 渲染流程 2 基础用法 2.1 基本绘图 2.2 多子图系统 2.3 高阶用法 2.3.1 自定义Artist对象 2.3.2 高级动画技术 2.3.3 事件处理系统 2.3.4 混合渲染技术 3 性能优化技巧 4 扩展模块 5 总结 5.1 底层原理关键点 5.2 进阶技巧 1 底层实现…

深入理解现代前端开发中的 <script type=“module“> 与构建工具实践

引言&#xff1a;模块化开发的演进在早期的前端开发中&#xff0c;JavaScript 缺乏原生的模块化支持&#xff0c;开发者不得不依赖 IIFE&#xff08;立即调用函数表达式&#xff09;或第三方库&#xff08;如 RequireJS&#xff09;来实现代码组织。随着 ES6&#xff08;ES2015…

yolo--qt可视化开发

qt5可能不支持我们的cuda版本&#xff0c;改用qt6 YOLO11QT6OpencvC训练加载模型全过程讲解_yolov11 模型转换成opencv c模型-CSDN博客 下面是qt5版本的案例&#xff0c;和yolo及cuda有冲突 安装qt 切换到虚拟环境&#xff0c;例如pyqt&#xff0c;conda activate pyqt pip …

SQL性能优化

show [session|global] status : 查看服务器状态 show global status like Com_ : 查看各种语句的执行次数 开启慢查询: 在 MySQL 配置文件&#xff08;/etc/my.cnf&#xff09;配置: #开启MySQL慢日志查询开关 slow_query_log1 #设置慢日志的时间为2秒&#xff0c;SQL语句执…

ctfshow pwn40

目录 1. 分析程序 2. 漏洞编写 3. 漏洞验证 1. 分析程序 首先检查程序相关保护&#xff0c;发现程序为32位且只开启了一个NX保护 checksec pwn 使用IDA进行逆向分析代码&#xff0c;查看漏洞触发点&#xff1a; 在main函数中&#xff0c;有一个ctfshow函数&#xff0c;这里…

SQL173 店铺901国庆期间的7日动销率和滞销率

SQL173 店铺901国庆期间的7日动销率和滞销率 SQL题解&#xff1a;店铺动销率与滞销率计算 关键&#xff1a;只要当天任一店铺有任何商品的销量就输出该天的结果&#xff0c;即使店铺901当天的动销率为0。 潜台词&#xff1a;​输出逻辑与店铺901的销售情况无关&#xff0c;只取…

PytorchLightning最佳实践基础篇

PyTorch Lightning&#xff08;简称 PL&#xff09;是一个建立在 PyTorch 之上的高层框架&#xff0c;核心目标是剥离工程代码与研究逻辑&#xff0c;让研究者专注于模型设计和实验思路&#xff0c;而非训练循环、分布式配置、日志管理等重复性工程工作。本文从基础到进阶&…

Apache Flink 实时流处理性能优化实践指南

Apache Flink 实时流处理性能优化实践指南 随着大数据和实时计算需求不断增长&#xff0c;Apache Flink 已经成为主流的流处理引擎。然而&#xff0c;在生产环境中&#xff0c;高并发、大吞吐量和低延迟的业务场景对 Flink 作业的性能提出了更高要求。本文将从原理层面深入解析…

ubuntu上将TempMonitor加入开机自动运行的方法

1.新建一个TempMonitor.sh文件&#xff0c;内容如下&#xff1a;#!/bin/bashcd /fjrobot/ ./TempMonitor &2.执行以下命令chmod x TempMonitor chmod x TempMonitor.sh rm -rf /etc/rc2.d/S56TempMonitor rm -rf /etc/init.d/TempMonitor cp /fjrobot/TempMonitor.sh /etc/…

速卖通自养号测评技术解析:IP、浏览器与风控规避的实战方案

一、速卖通的“春天”来了&#xff0c;卖家如何抓住机会&#xff1f;2025年的夏天&#xff0c;速卖通的风头正劲。从沙特市场跃升为第二大电商平台&#xff0c;到8月大促返佣力度升级&#xff0c;平台对优质商家的扶持政策越来越清晰。但与此同时&#xff0c;竞争也愈发激烈——…

adb: CreateProcessW failed: 系统找不到指定的文件

具体错误 adb devices * daemon not running; starting now at tcp:5037 adb: CreateProcessW failed: 系统找不到指定的文件。 (2) * failed to start daemon adb.exe: failed to check server version: cannot connect to daemon 下载最新的platform-tools-windows 下载最新…

Centos安装HAProxy搭建Mysql高可用集群负载均衡

接上文MYSQL高可用集群搭建–docker https://blog.csdn.net/weixin_43914685/article/details/149647589?spm1001.2014.3001.5501 连接到你搭建的 Percona XtraDB Cluster (PXC) 数据库集群&#xff0c;实现高可用性和负载均衡&#xff0c;建议使用一个中间件来管理这些连接。…

Sql server开挂的OPENJSON

以前一直用sql server2008&#xff0c;自从升级成sql server2019后&#xff0c;用OPENJSON的感觉像开挂&#xff0c;想想以前表作为参数传输时的痛苦&#xff0c;不堪回首。一》不堪回首 为了执行效率&#xff0c;很多时候希望将表作为参数传给数据库的存储过程。存储过程支持自…

【数据结构】队列和栈练习

1.用队列实现栈 225. 用队列实现栈 - 力扣&#xff08;LeetCode&#xff09; typedef int QDatatype; typedef struct QueueNode {struct QueueNode *next;QDatatype data; }QNode;typedef struct Queue {QNode* head;QNode* tail;QDatatype size; }Que;typedef struct {Que…