【C语言】8.C语言操作符详解(1)
文章目录
- 1.操作符的分类
- 2.⼆进制和进制转换
- 3.原码、反码、补码
- 4.移位操作符
- 4.1 左移操作符
- 4.2 右移操作符
- 5.位操作符:&、|、^、~
- 5.1 &:按位与
- 5.2 |:按位或
- 5.3 ^:按位异或
- 5.4 ~:按位取反
- 5.5 例题
- 例题1
- 例题2
- 例题3
- 例题4
1.操作符的分类
-
算术操作符:
+、-、*、/、% -
移位操作符:
<<,>> -
位操作符:
&,|,^ -
赋值操作符:
=、+=、-=、*=、/=、%=、<<=、>>=、&=、|=、^= -
单目操作符:
!、++、--、&、*、+、-、~、sizeof、(类型) -
关系操作符:
>、>=、<、<=、==、!= -
逻辑操作符:
&&、|| -
条件操作符:
? : -
逗号表达式:
, -
下标引用:
[] -
函数调用:
() -
结构成员访问:
.、->
2.⼆进制和进制转换
进制转换的教程网上比比皆是,而且视频看起来肯定比文字清晰。这里就不过多赘述了。
我们需要掌握一下几个:
- 2进制
转10进制 - 10进制
转2进制 - 2进制
转8进制和16进制 - 8进制和16进制
转2进制 - 8进制
转16进制 - 16进制
转8进制
3.原码、反码、补码
整数的2进制表示方法有三种:
-
原码
-
反码
-
补码
有符号整数的三种表示方法均有符号位和数值位两部分,2进制序列中,最高位的1位是被当做符号位,剩余的都是数值位。
符号位都是用0表示“正”,用1表示“负”。
正整数的原、反、补码都相同。
原码:直接将数值按照正负数的形式翻译成二进制得到的就是原码。
反码:正数反码和原码一样。
补码:正数补码和原码一样。
负整数的三种表示方法各不相同。
原码:直接将数值按照正负数的形式翻译成二进制得到的就是原码。(注意符号位)
反码:将原码的符号位不变,其他位依次按位取反就可以得到反码。
补码:反码+1就得到补码。
4.移位操作符
只有整数才能运用移位操作符。
4.1 左移操作符
例1:
#include <stdio.h>
int main()
{int num = 10;int n = num<<1;//10补码: 00000000 00000000 00000000 00001010//10<<1补码:0 00000000 00000000 00000000 00010100//这里最前面的0被丢掉了printf("n= %d\n", n);printf("num= %d\n", num);return 0;
}
打印:
n= 20
num= 10
例2:
#include <stdio.h>
int main()
{int num = -1;int n = num<<1;//-1原码: 10000000 00000000 00000000 00000001//-1反码: 11111111 11111111 11111111 11111110//-1补码: 11111111 11111111 11111111 11111111
//-1<<1补码:0 11111111 11111111 11111111 11111110//这里最前面的0被丢掉了printf("n= %d\n", n);printf("num= %d\n", num);return 0;
}
打印:
n= -2
num= -1
4.2 右移操作符
右移运算分两种:
-
逻辑右移:左边用0填充,右边丢弃。
-
算术右移:左边用原该值的符号位填充(正数左边补0,负数左边补1),右边丢弃。
右移是算术右移还是逻辑右移是取决于编译器的。通常采用的都是算数右移。
例1:
#include <stdio.h>
int main()
{int num = -10;//-10原码:10000000 00000000 00000000 00001010//-10反码:11111111 11111111 11111111 11110101//-10补码:11111111 11111111 11111111 11110110//逻辑右移:01111111 11111111 11111111 11111011 |0(这个0被丢弃了)//算术右移:11111111 11111111 11111111 11111011 |0(这个0被丢弃了)//这里采用算数右移//右移补码:11111111 11111111 11111111 11111011//右移反码:10000000 00000000 00000000 00000100//右移原码:10000000 00000000 00000000 00000101--->-5int n = num>>1;printf("n= %d\n", n);printf("num= %d\n", num);return 0;
}
打印:
n= -5
num= -10
5.位操作符:&、|、^、~
双目操作符:
- &:按位与
- |:按位或
- ^:按位异或
单目操作符:
- ~:按位取反
5.1 &:按位与
有0则0。
#include <stdio.h>
int main()
{int a = 6;// 6的补码:00000000 00000000 00000000 00000110int b = -7;//-7的原码:10000000 00000000 00000000 00000111//-7的反码:11111111 11111111 11111111 11111000//-7的补码:11111111 11111111 11111111 11111001int c = a & b;// 6的补码:00000000 00000000 00000000 00000110//-7的补码:11111111 11111111 11111111 11111001//a & b补码::00000000 00000000 00000000 00000000-->0printf("n= %d\n", c);return 0;
}
打印:
n= 0
5.2 |:按位或
有1则1。
#include <stdio.h>
int main()
{int a = 6;// 6的补码:00000000 00000000 00000000 00000110int b = -7;//-7的原码:10000000 00000000 00000000 00000111//-7的反码:11111111 11111111 11111111 11111000//-7的补码:11111111 11111111 11111111 11111001int c = a | b;// 6的补码:00000000 00000000 00000000 00000110//-7的补码:11111111 11111111 11111111 11111001//a | b补码:11111111 11111111 11111111 11111111//a | b反码:10000000 00000000 00000000 00000000//a | b原码:10000000 00000000 00000000 00000001-->-1printf("n= %d\n", c);return 0;
}
打印:
n= -1
5.3 ^:按位异或
相同为0,不同为1。
#include <stdio.h>
int main()
{int a = 6;// 6的补码:00000000 00000000 00000000 00000110int b = -7;//-7的原码:10000000 00000000 00000000 00000111//-7的反码:11111111 11111111 11111111 11111000//-7的补码:11111111 11111111 11111111 11111001int c = a ^ b;// 6的补码:00000000 00000000 00000000 00000110//-7的补码:11111111 11111111 11111111 11111001//a ^ b补码:11111111 11111111 11111111 11111111//a ^ b反码:10000000 00000000 00000000 00000000//a ^ b原码:10000000 00000000 00000000 00000001-->-1printf("n= %d\n", c);return 0;
}
打印:
n= -1
5.4 ~:按位取反
按2进制位取反
#include <stdio.h>
int main()
{int a = 0;//0的原码:00000000 00000000 00000000 00000000//~a补码: 11111111 11111111 11111111 11111111//~a反码: 10000000 00000000 00000000 00000000 //~a原码: 10000000 00000000 00000000 00000001-->-1printf("n= %d\n", ~a);return 0;
}
打印:
n= -1
5.5 例题
例题1
不创建临时变量(第三个变量),实现两个整数的交换。
方法1:
int main() {int a = 3;int b = 5;printf("交换前:a=%d b=%d\n", a, b);a = a + b;b = a - b;a = a - b;printf("交换后:a=%d b=%d\n", a, b);return 0;
}
打印:
交换前:a=3 b=5
交换后:a=5 b=3
上面这个方法有点问题,如果a+b的和超过了一个整型数据的存储大小,那么就计算不了了。
方法2:
int main() {int a = 3;int b = 5;printf("交换前:a=%d b=%d\n", a, b);a = a ^ b;b = a ^ b;a = a ^ b;printf("交换后:a=%d b=%d\n", a, b);return 0;
}
打印:
交换前:a=3 b=5
交换后:a=5 b=3
为什么呢?
因为异或操作符,相同两个数异或为0。
3^3=0
a^a=0
0异或任何数都为数的本身 。
0^3=3
0^a=a
异或是支持交换率的。
例题2
编写代码实现:求一个整数存储在内存中的二进制中1的个数。
int count_bit_onr(unsigned int n) {int count = 0;while (n) {if ((n % 2) == 1) {count++;}n = n / 2;}return count;
}int main() {int num = 0;scanf("%d", &num);int ret = count_bit_onr(num);printf("%d\n", ret);return 0;
}
输入:
15
打印:
4
也可以这么写:
int count_bit_onr(int n) {int i = 0;int count = 0;for (i = 0; i < 32; i++) {if ((n >> 1) & 1 == 1) {count++;}}return count;
}int main() {int num = 0;scanf("%d", &num);int ret = count_bit_onr(num);printf("%d\n", ret);return 0;
}
输入-1会打印32
这个算法的原理:
-1补码:11111111 11111111 11111111 11111111
1补码: 00000000 00000000 00000000 00000001
-1&1= 00000000 00000000 00000000 00000001
不论-1的补码前面多少个1,只要和1按位与后就只看最后一位是不是1。
然后运用移位操作符,将每一位都和1按位与,统计出一共多少个1。
其实还有更加巧妙地算法:
n=n&(n-1)
例如:n=11
n = 1011
n-1 = 1010
n&(n-1) = 1010
因为n=n&(n-1),所以现在新的n是1010
n = 1010
n-1 = 1001
n&(n-1) = 1000
因为n=n&(n-1),所以现在新的n是1000
n = 1000
n-1 = 0111
n&(n-1) = 0000
从这三次变化里面我们可以看到,我们执行了一次n=n&(n-1),那么n最右面那个1就会消失。把所有的1都去掉后就变成0了。
例题3
写一个代码,判断n是否为2的次方数。
首先我们先看看2的次方数:
000010
000100
001000
010000
100000
可以看出2的次方数里面只有1个1。
if (n & (n - 1) == 0) {printf("yes")
}
例题4
编写代码,将13二进制序列的第五位修改为1,然后改回0。
第5位改成1,第5位就和1或|,其他位都是0。
第5位改为0,第5位就和0与&,其他位都是1。
int main() {int a = 13;//13原码:00000000 00000000 00000000 00001101//13补码:00000000 00000000 00000000 00001101//16补码:00000000 00000000 00000000 00010000//16|13:00000000 00000000 00000000 00011101-->29int n = 5;a = a | (1 << (n - 1));printf("%d\n", a);a &= ~(a << (n - 1));printf("%d\n", a);return 0;
}
打印:
29
13
相关文章:
【C语言】8.C语言操作符详解(1)
文章目录 1.操作符的分类2.⼆进制和进制转换3.原码、反码、补码4.移位操作符4.1 左移操作符4.2 右移操作符 5.位操作符:&、|、^、~5.1 &:按位与5.2 |:按位或5.3 ^:按位异或5.4 ~:按位取反5.5 例题例题1例题2例…...
Buzz库网络爬虫实例:快速爬取百度搜索实时热点
前言 随着互联网的发展,信息获取已经成为了人们日常生活和工作中的重要一环。而在信息获取的过程中,网络爬虫作为一种自动化的数据采集工具,为我们提供了极大的便利。本文将介绍如何利用PHP编写一个简单而高效的网络爬虫,实现快速…...
SQL注入:pikachu靶场中的SQL注入通关
目录 1、数字型注入(post) 2、字符型注入(get) 3、搜索型注入 4、XX型注入 5、"insert/update"注入 Insert: update: 6、"delete"注入 7、"http header"注入 8、盲…...
springsecurity入门登录授权
①我们需要自定义登陆接口,也就是在controller目录新建LoginController类,在controller方法里面去调用service接口,在service接口实现AuthenticationManager去进行用户的认证,注意,我们定义的controller方法要让Spring…...
医学科技查新中对查新点的撰写方法!附案例讲解!
我国的科技查新工作最早是从医学领域开始的,始于1985年中国科学院医学情报所,后来逐步发展到工、农等其 他各个领域。医学科技查新包括立项查新和成果查新两个部分,其中医学立项查新,它是指在医学科研项目申报开题之前,…...
2024最新流媒体在线音乐系统网站源码| 音乐社区 | 多语言 | 开心版
2024最新流媒体在线音乐系统网站源码| 音乐社区 | 多语言 | 开心版 https://download.csdn.net/download/huayula/89347742...
回溯算法05(leetcode491/46/47)
参考资料: https://programmercarl.com/0491.%E9%80%92%E5%A2%9E%E5%AD%90%E5%BA%8F%E5%88%97.html 491. 非递减子序列 题目描述: 给你一个整数数组 nums ,找出并返回所有该数组中不同的递增子序列,递增子序列中 至少有两个元素…...
Transformer,革命性的深度学习架构
Transformer 是一种革命性的深度学习架构,专门设计用于处理序列数据,特别是在自然语言处理(NLP)任务中表现卓越。它由 Vaswani 等人在 2017 年发表的论文《Attention is All You Need》中首次提出,打破了当时基于循环神经网络(RNN)和卷积神经网络(CNN)的序列建模常规,…...
实验五:实现循环双链表各种基本运算的算法
实验五:实现循环双链表各种基本运算的算法 一、实验目的与要求 目的:领会循环双链表存储结构和掌握循环双链表中各种基本运算算法设计。 内容:编写一个程序cdinklist.cpp,实现循环双链表的各种基本运算和整体建表算法(假设循环双链表的元素类型ElemType为char),并…...
ElasticSearch IK分词器的安装、词典扩展与停用
🏷️个人主页:牵着猫散步的鼠鼠 🏷️系列专栏:云原生与服务部署-专栏 🏷️个人学习笔记,若有缺误,欢迎评论区指正 目录 编辑 1. 前言 2. IK分词器安装 3. IK分词器词典扩展与停用 4. 总…...
代码随想录训练营总结
为期两个月的代码随想录训练营今天结束了,我想我的收获是非常大的。进到训练营的大群里,令我有种安心的感觉,原来世界各地有这么多与我一起努力的伙伴。更令人安心的是知识星球对于学习进度的规划,细化到每一天每道题,…...
深度学习-转置卷积
转置卷积 转置卷积(Transposed Convolution),也被称为反卷积(Deconvolution),是深度学习中的一种操作,特别是在卷积神经网络(CNN)中。它可以将一个低维度的特征图&#x…...
Unity性能优化工具介绍
文章目录 一.Stats组件1.Audio音频的数据组件:2.图形数据 二.Profiler 性能分析器 一.Stats组件 Unity自带Statistics(统计数据),Game视窗中点击Stats打开 1.Audio音频的数据组件: 1):Level 声音强度 单位是分贝(dB) 表示音频听声音的大小,是闪烁波动的. 2):SDPload 数据信…...
Math之向上向下取整
有时我们会遇到向上和向下取整的操作,这时我们可以使用Math类来进行操作。 1、向上取整 Math.ceil() 方法返回大于或等于指定表达式的最小整数(即向上取整)。如果参数是一个整数,那么结果就是这个整数本身。 示例: …...
MPP架构
MPP架构,即Massively Parallel Processing(大规模并行处理)架构,是一种用于处理大规模数据的并行计算架构。它通过将数据和计算能力分布在多个处理节点上,利用并行处理技术来加速数据处理和分析的速度。 在MPP架构中&…...
These relative modules were not found:* ../../../constant in
这个错误信息表明,你的项目在尝试加载一个相对路径模块 ../../../constant 时遇到了问题。具体来说,它在 ./node_modules/cache-loader/dist/cj 这个路径下找不到这个模块。 这里有几个可能的原因和相应的解决方案: 路径错误:首…...
2024最新彩虹聚合DNS管理系统源码v1.3 全开源
2024最新彩虹聚合DNS管理系统源码v1.3 全开源 聚合DNS管理系统可以实现在一个网站内管理多个平台的域名解析,目前已支持的域名平台有:阿里云、腾讯云、华为云、西部数码、DNSLA、CloudFlare。 本系统支持多用户,每个用户可分配不同的域名解…...
在Go语言中如何实现变参函数和函数选项模式
在Go语言编程中,我们经常会遇到需要给函数传递可选参数的情况。传统的做法是定义一个结构体,将所有可选参数作为结构体字段,然后在调用函数时创建该结构体的实例并传递。这种方式虽然可行,但是当可选参数较多时,创建结构体实例的代码就会变得冗长และ不太直观。 Go语言的一个…...
Spring Boot中的 6 种API请求参数读取方式
使用Spring Boot开发API的时候,读取请求参数是服务端编码中最基本的一项操作,Spring Boot中也提供了多种机制来满足不同的API设计要求。 接下来,就通过本文,为大家总结6种常用的请求参数读取方式。如果你发现自己知道的不到6种&a…...
Linux基础命令[27]-gpasswd
文章目录 1. gpasswd 命令说明2. gpasswd 命令语法3. gpasswd 命令示例3.1 不加参数3.2 -a(将用户加入组)3.3 -d(从组中删除用户)3.4 -r(删除组密码)3.5 -M(多个用户一起加入组)3.6 …...
从零实现富文本编辑器#5-编辑器选区模型的状态结构表达
先前我们总结了浏览器选区模型的交互策略,并且实现了基本的选区操作,还调研了自绘选区的实现。那么相对的,我们还需要设计编辑器的选区表达,也可以称为模型选区。编辑器中应用变更时的操作范围,就是以模型选区为基准来…...
Linux简单的操作
ls ls 查看当前目录 ll 查看详细内容 ls -a 查看所有的内容 ls --help 查看方法文档 pwd pwd 查看当前路径 cd cd 转路径 cd .. 转上一级路径 cd 名 转换路径 …...
【ROS】Nav2源码之nav2_behavior_tree-行为树节点列表
1、行为树节点分类 在 Nav2(Navigation2)的行为树框架中,行为树节点插件按照功能分为 Action(动作节点)、Condition(条件节点)、Control(控制节点) 和 Decorator(装饰节点) 四类。 1.1 动作节点 Action 执行具体的机器人操作或任务,直接与硬件、传感器或外部系统…...
Axios请求超时重发机制
Axios 超时重新请求实现方案 在 Axios 中实现超时重新请求可以通过以下几种方式: 1. 使用拦截器实现自动重试 import axios from axios;// 创建axios实例 const instance axios.create();// 设置超时时间 instance.defaults.timeout 5000;// 最大重试次数 cons…...
华为云Flexus+DeepSeek征文|DeepSeek-V3/R1 商用服务开通全流程与本地部署搭建
华为云FlexusDeepSeek征文|DeepSeek-V3/R1 商用服务开通全流程与本地部署搭建 前言 如今大模型其性能出色,华为云 ModelArts Studio_MaaS大模型即服务平台华为云内置了大模型,能助力我们轻松驾驭 DeepSeek-V3/R1,本文中将分享如何…...
【Redis】笔记|第8节|大厂高并发缓存架构实战与优化
缓存架构 代码结构 代码详情 功能点: 多级缓存,先查本地缓存,再查Redis,最后才查数据库热点数据重建逻辑使用分布式锁,二次查询更新缓存采用读写锁提升性能采用Redis的发布订阅机制通知所有实例更新本地缓存适用读多…...
Vue ③-生命周期 || 脚手架
生命周期 思考:什么时候可以发送初始化渲染请求?(越早越好) 什么时候可以开始操作dom?(至少dom得渲染出来) Vue生命周期: 一个Vue实例从 创建 到 销毁 的整个过程。 生命周期四个…...
tauri项目,如何在rust端读取电脑环境变量
如果想在前端通过调用来获取环境变量的值,可以通过标准的依赖: std::env::var(name).ok() 想在前端通过调用来获取,可以写一个command函数: #[tauri::command] pub fn get_env_var(name: String) -> Result<String, Stri…...
认识CMake并使用CMake构建自己的第一个项目
1.CMake的作用和优势 跨平台支持:CMake支持多种操作系统和编译器,使用同一份构建配置可以在不同的环境中使用 简化配置:通过CMakeLists.txt文件,用户可以定义项目结构、依赖项、编译选项等,无需手动编写复杂的构建脚本…...
消息队列系统设计与实践全解析
文章目录 🚀 消息队列系统设计与实践全解析🔍 一、消息队列选型1.1 业务场景匹配矩阵1.2 吞吐量/延迟/可靠性权衡💡 权衡决策框架 1.3 运维复杂度评估🔧 运维成本降低策略 🏗️ 二、典型架构设计2.1 分布式事务最终一致…...
