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

嵌入式知识点总结 C/C++ 专题提升(七)-位操作

  针对于嵌入式软件杂乱的知识点总结起来,提供给读者学习复习对下述内容的强化。

目录

1.位操作基础

2.如何求解整型数的二进制表示中1的个数 ?

3.如何求解二进制中0的个数

4.交换两个变量的值,不使用第三个变量。即a=3,b=5,交换之后a=5,b=3:

5.给定一个整型变量a,写两段代码,第一个设置a的bit3,第二个清除a 的bit 3。在以上两个操作中,要保持其它位不变。


1.位操作基础

位操作(Bitwise Operations)是直接对二进制位进行操作的一类运算,广泛应用于嵌入式开发、系统编程、算法设计等领域。以下是常用的位操作及其作用、示例。

按位与 (&)

将两个数的每个位进行与运算。

规则:1 & 1 = 1,其余为 0。

作用:用于清零某些位,提取特定位。

示例:清除一个数的低 4 位

int x = 0b11010101; // 213
int result = x & 0b11110000; // 清除低4位
printf("Result: 0x%x\n", result); // 输出: 0xd0

按位或 (|)

将两个数的每个位进行或运算。

规则:0 | 0 = 0,其余为 1。

作用:用于设置某些位为 1。

示例:设置某数的第 3 位为 1

int x = 0b11000001; // 193
int result = x | 0b00000100; // 设置第3位
printf("Result: 0x%x\n", result); // 输出: 0xc5

按位异或 (^)

将两个数的每个位进行异或运算。

规则:相同为 0,不同为 1。

作用:用于翻转特定位,或无进位加法。

示例:翻转某数的第 3 位

int x = 0b11000001; // 193
int result = x ^ 0b00000100; // 翻转第3位
printf("Result: 0x%x\n", result); // 输出: 0xc5

按位取反 (~)

将每个位取反,0 变 1,1 变 0。

作用:用于生成补码、求反值。

示例:取反某数

int x = 0b00001111; // 15
int result = ~x; // 取反
printf("Result: 0x%x\n", result); // 输出: 0xfffffff0 (补码表示)

左移 (<<)

将二进制位左移,低位补 0。

作用:快速乘以 2 的幂。

示例:将某数左移 2 位

int x = 5; // 0b0101
int result = x << 2; // 左移2位
printf("Result: %d\n", result); // 输出: 20

右移 (>>)

将二进制位右移,高位补符号位(算术右移)或 0(逻辑右移)。

作用:快速除以 2 的幂。

示例:将某数右移 2 位

int x = 20; // 0b00010100
int result = x >> 2; // 右移2位
printf("Result: %d\n", result); // 输出: 5

在嵌入式开发中,位操作非常常见,以下是一些典型应用场景和代码示例:

1. 控制寄存器的位操作

设置某些位

设置寄存器中某些位为 1,比如配置 GPIO 为输出模式。

#define GPIO_DIR_REG  (*(volatile unsigned int *)0x40020000) // 假设寄存器地址
#define GPIO_PIN_3    (1 << 3) // 第3位表示GPIO3void set_gpio_output() {GPIO_DIR_REG |= GPIO_PIN_3; // 设置第3位为1
}

清除某些位

清除寄存器中某些位为 0,比如禁用某外设功能。

void disable_feature() {GPIO_DIR_REG &= ~GPIO_PIN_3; // 清除第3位
}

2. 检测某个位的状态

判断某引脚状态

检测某引脚的高低电平。

#define GPIO_INPUT_REG (*(volatile unsigned int *)0x40020010) // 输入寄存器int is_pin_high() {return (GPIO_INPUT_REG & GPIO_PIN_3) ? 1 : 0; // 检查第3位是否为1
}

3. 翻转某个位

翻转 LED 状态

嵌入式中控制 LED 灯时,经常需要翻转某 GPIO 的状态。

#define GPIO_OUTPUT_REG (*(volatile unsigned int *)0x40020004) // 输出寄存器void toggle_led() {GPIO_OUTPUT_REG ^= GPIO_PIN_3; // 翻转第3位
}

4. 提取寄存器的特定位

获取外设状态

从状态寄存器中提取某外设的状态位。

#define STATUS_REG  (*(volatile unsigned int *)0x40020020) // 状态寄存器
#define DEVICE_READY_BIT (1 << 7) // 第7位表示设备准备好int is_device_ready() {return (STATUS_REG & DEVICE_READY_BIT) >> 7; // 提取第7位
}

5. 多位配置操作

设置多位

一次性设置多个位,比如配置多个 GPIO 为输出模式。

#define GPIO_OUTPUT_MASK (GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5)void configure_multiple_gpio() {GPIO_DIR_REG |= GPIO_OUTPUT_MASK; // 设置GPIO3、GPIO4、GPIO5为1
}

清除多位

清除多个位。

void clear_multiple_gpio() {GPIO_DIR_REG &= ~GPIO_OUTPUT_MASK; // 清除GPIO3、GPIO4、GPIO5
}

6. 数据压缩与解压

压缩数据

将多个小数据合并到一个 32 位变量中。

unsigned int pack_data(unsigned char a, unsigned char b, unsigned char c, unsigned char d) {return (a << 24) | (b << 16) | (c << 8) | d;
}

解压数据

从一个变量中提取多个字段。

void unpack_data(unsigned int packed, unsigned char *a, unsigned char *b, unsigned char *c, unsigned char *d) {*a = (packed >> 24) & 0xFF;*b = (packed >> 16) & 0xFF;*c = (packed >> 8) & 0xFF;*d = packed & 0xFF;
}

2.如何求解整型数的二进制表示中1的个数 ?

#include <stdio.h>int func(int x) {int countx = 0; // 计数器初始化while (x) {countx++;x = x & (x - 1); // 清除最低位的1}return countx;
}int main() {printf("%d\n", func(9999)); // 调用函数并打印结果return 0;
}

func 函数

用于计算输入整数 x 的二进制表示中有多少个 1

x = x & (x - 1) 的作用是清除 x 中最低位的 1,直到 x 变为 0

每次清除一个 1 时,countx 增加 1。

main 函数

调用 func(9999),计算 9999 的二进制表示中有多少个 1

使用 printf 输出结果。

输出结果

9999 的二进制表示为 10011100001111,其中有 8 个 1

3.如何求解二进制中0的个数还有1的个数

#include <stdio.h>void count_ones_and_zeros(int x) {int count_ones = 0, count_zeros = 0;while (x) {if (x & 1) {count_ones++;  // 如果最低位是 1} else {count_zeros++;  // 如果最低位是 0}x >>= 1;  // 右移一位,检查下一位}// 如果 x 最后的结果为 0,还需要考虑 x 可能有零填充的位// 假设我们处理的整数位数为 32 位int total_bits = sizeof(x) * 8;  // 通常为 32 位(对于 32 位整数)count_zeros = total_bits - count_ones - count_zeros;printf("1's: %d, 0's: %d\n", count_ones, count_zeros);
}int main() {int numbers[] = {25, 15, 5};for (int i = 0; i < 3; i++) {printf("For %d: ", numbers[i]);count_ones_and_zeros(numbers[i]);}return 0;
}

4.交换两个变量的值,不使用第三个变量。即a=3,b=5,交换之后a=5,b=3:

#include <stdio.h>int main() {int a = 3, b = 5;printf("Before swap: a = %d, b = %d\n", a, b);a = a + b; // a 变为 8 (3 + 5)b = a - b; // b 变为 3 (8 - 5)a = a - b; // a 变为 5 (8 - 3)printf("After swap: a = %d, b = %d\n", a, b);return 0;
}

a = a + ba 保存了 ab 的和。

b = a - bb 通过从 a 的和中减去原来的 b 值,得到原来的 a 值。

a = a - ba 通过从和中减去新的 b 值,得到原来的 b 值。

#include <stdio.h>int main() {int a = 3, b = 5;// a 0011  b 0101printf("Before swap: a = %d, b = %d\n", a, b);a = a ^ b; // a 变为 6 (3 ^ 5) 0011 0101  - 0110b = a ^ b; // b 变为 3 (6 ^ 5) 0110 0101  - 0011a = a ^ b; // a 变为 5 (6 ^ 3) 0110 0011  - 0101printf("After swap: a = %d, b = %d\n", a, b);return 0;
}

a = a ^ ba 变成了 ab 的异或值。

b = a ^ bb 通过异或 a(当前是 a ^ b)得到原来的 a 值。

a = a ^ ba 通过异或 b(当前是原来的 a 值)得到原来的 b 值。

5.给定一个整型变量a,写两段代码,第一个设置a的bit3,第二个清除a 的bit 3。在以上两个操作中,要保持其它位不变。

#include <stdio.h>
#define BIT3 (1<<3)
static int a=5;
void Set_Bit3(void){a |= BIT3;
}
void Clear_Bit3(void){a &= ~BIT3;
}
int main() {Set_Bit3();Clear_Bit3();printf("%d",a);return 0;
}

假设 a 的初始值为 5,其二进制为 00000101

初始值打印:5

设置第3位后:

BIT3 = 1 << 3 = 00001000

a | BIT3 = 00000101 | 00001000 = 00001101,结果为 13

打印:13

清除第3位后:

~BIT3 = ~00001000 = 11110111

a & ~BIT3 = 00001101 & 11110111 = 00000101,结果为 5

打印:5

相关文章:

嵌入式知识点总结 C/C++ 专题提升(七)-位操作

针对于嵌入式软件杂乱的知识点总结起来&#xff0c;提供给读者学习复习对下述内容的强化。 目录 1.位操作基础 2.如何求解整型数的二进制表示中1的个数 ? 3.如何求解二进制中0的个数 4.交换两个变量的值&#xff0c;不使用第三个变量。即a3,b5,交换之后a5,b3: 5.给定一个…...

新星杯-ESP32智能硬件开发--ESP32的I/O组成

本博文内容导读&#x1f4d5;&#x1f389;&#x1f525; ESP32系统的基础外设开发&#xff1a;IO_MUX和GPIO矩阵 IO_MUX和GPIO矩阵 ESP32的I/O组成了与外部世界交互的基础&#xff0c;ESP32芯片有34个物理GPIO引脚。每个引脚都可用作一个通用I/O&#xff0c;或者连接一个内部…...

航空航天混合动力(7)航空航天分布式电推进系统

航空航天分布式电推进系统 1.概述2.分布式电推进系统组成3.关键技术4.分布式电推进系统优势5.国内外研究情况5.1 国外5.2 国内6.分布式电推进系统应用场景6.1 航空领域6.2 航天领域tips:资料来自网上,仅供参考学习使用 1.概述 分布式推进系统是指飞行器推力由位于整个航空器…...

AIGC视频生成明星——Emu Video模型

大家好&#xff0c;这里是好评笔记&#xff0c;公主号&#xff1a;Goodnote&#xff0c;专栏文章私信限时Free。本文详细介绍Meta的视频生成模型Emu Video&#xff0c;作为Meta发布的第二款视频生成模型&#xff0c;在视频生成领域发挥关键作用。 &#x1f33a;优质专栏回顾&am…...

Cyber Security 101-Security Solutions-Firewall Fundamentals(防火墙基础)

了解防火墙并亲身体验 Windows 和 Linux 内置防火墙。 任务1&#xff1a;防火墙的用途是什么 我们看到商场、银行、 餐馆和房屋。这些警卫被安置在 这些区域用于检查进出人员。这 维护此检查的目的是确保没有人在没有 被允许。这个警卫充当了他所在区域和访客之间的一堵墙。 …...

备赛蓝桥杯之第十五届职业院校组省赛第一题:智能停车系统

提示&#xff1a;本篇文章仅仅是作者自己目前在备赛蓝桥杯中&#xff0c;自己学习与刷题的学习笔记&#xff0c;写的不好&#xff0c;欢迎大家批评与建议 由于个别题目代码量与题目量偏大&#xff0c;请大家自己去蓝桥杯官网【连接高校和企业 - 蓝桥云课】去寻找原题&#xff0…...

Docker核心命令与Yocto项目的高效应用

随着软件开发逐渐向分布式和容器化方向演进&#xff0c;Docker 已成为主流的容器化技术之一。它通过标准化的环境配置、资源隔离和高效的部署流程&#xff0c;大幅提高了开发和构建效率。Yocto 项目作为嵌入式 Linux 系统构建工具&#xff0c;与 Docker 的结合进一步增强了开发…...

idea plugin插件开发——入门级教程(IntelliJ IDEA Plugin)

手打不易&#xff0c;如果转摘&#xff0c;请注明出处&#xff01; 注明原文&#xff1a;idea plugin插件开发——入门级教程&#xff08;IntelliJ IDEA Plugin&#xff09;-CSDN博客 目录 前言 官方 官方文档 代码示例 开发前必读 Intellij、Gradle、JDK 版本关系 plu…...

61,【1】BUUCTF WEB BUU XSS COURSE 11

进入靶场 左边是吐槽&#xff0c;右边是登录&#xff0c;先登录试试 admin 123456 admiin# 123456 admin"# 123456 不玩了&#xff0c;先去回顾下xss 回顾完就很尴尬了&#xff0c;我居然用SQL的知识去做xss的题 重来 吐槽这里有一个输入框&#xff0c;容易出现存储型…...

开发环境搭建-1:配置 WSL (类 centos 的 oracle linux 官方镜像)

一些 Linux 基本概念 个人理解&#xff0c;并且为了便于理解&#xff0c;可能会存在一些问题&#xff0c;如果有根本上的错误希望大家及时指出 发行版 WSL 的系统是基于特定发行版的特定版本的 Linux 发行版 有固定组织维护的、开箱就能用的 Linux 发行版由固定的团队、社…...

Spring Boot MyBatis Plus 版本兼容问题(记录)

Spring Boot & MyBatis Plus 版本兼容问题&#xff08;Invalid value type for attribute factoryBeanObjectType: java.lang.String&#xff09; 问题描述问题排查1. 检查 MapperScan 的路径2. 项目中没有配置 FactoryBean3. 检查 Spring 和 MyBatis Plus 版本兼容性 解决…...

26. 【.NET 8 实战--孢子记账--从单体到微服务】--需求更新--用户注销、修改用户名、安全设置

在实际开发过程中&#xff0c;项目需求的变更和增加是常见的情况&#xff0c;因此这篇文章我们就模拟一下项目需求新增的情况。 一、需求 项目经理今天提出了新的功能&#xff0c;需要增加重置密码、安全设置、修改用户名、注销账户这四个功能&#xff0c;这四个功能必须是独…...

神经网络|(一)加权平均法,感知机和神经元

【1】引言 从这篇文章开始&#xff0c;将记述对神经网络知识的探索。相关文章都是学习过程中的感悟和理解&#xff0c;如有雷同或者南辕北辙的表述&#xff0c;请大家多多包涵。 【2】加权平均法 在数学课本和数理统计课本中&#xff0c;我们总会遇到求一组数据平均值的做法…...

OpenHarmony OTA升级参考资料记录

OpenHarmony 作为一个开源分布式操作系统,通过其强大的 OTA(Over-The-Air)升级能力,为开发者和厂商提供了一套灵活而安全的系统升级方案。 OTA升级方式 根据升级包的应用方式,OpenHarmony 的 OTA 升级可以分为两种:本地升级和网络OTA升级。 本地升级 本地升级是将已制作…...

在 Kubernetes 上快速安装 KubeSphere v4.1.2

目录标题 安装文档配置repo安装使用插件 安装文档 在 Kubernetes 上快速安装 KubeSphere 配置repo export https_proxy10.10.x.x:7890 helm repo add stable https://charts.helm.sh/stable helm repo update安装 helm upgrade --install -n kubesphere-system --create-name…...

【回忆迷宫——处理方法+DFS】

题目 代码 #include <bits/stdc.h> using namespace std; const int N 250; int g[N][N]; bool vis[N][N]; int dx[4] {0, 0, -1, 1}; int dy[4] {-1, 1, 0, 0}; int nx 999, ny 999, mx, my; int x 101, y 101; //0墙 (1空地 2远方) bool jud(int x, int y) {if…...

华为OD机试真题---战场索敌

华为OD机试真题“战场索敌”是一道考察算法和数据结构应用能力的题目。以下是对该题目的详细解析&#xff1a; 一、题目描述 有一个大小是NM的战场地图&#xff0c;被墙壁’#‘分隔成大小不同的区域。上下左右四个方向相邻的空地’.‘属于同一个区域&#xff0c;只有空地上可…...

计算机网络 (53)互联网使用的安全协议

一、SSL/TLS协议 概述&#xff1a; SSL&#xff08;Secure Sockets Layer&#xff09;安全套接层和TLS&#xff08;Transport Layer Security&#xff09;传输层安全协议是工作在OSI模型应用层的安全协议。SSL由Netscape于1994年开发&#xff0c;广泛应用于基于万维网的各种网络…...

c++算法贪心系列

本篇文章&#xff0c;同大家一起学习贪心算法&#xff01;&#xff01;&#xff01; 第一题 题目链接 2208. 将数组和减半的最少操作次数 - 力扣&#xff08;LeetCode&#xff09; 题目解析 本题重点&#xff1a;最终的数组和要小于原数组和的一半&#xff0c;且求这一操作的…...

【Maui】注销用户,采用“手势”点击label弹窗选择

文章目录 前言一、问题描述二、解决方案三、软件开发&#xff08;源码&#xff09;3.1 方法一&#xff1a;前端绑定3.2 方法二&#xff1a;后端绑定3.3 注销用户的方法 四、项目展示 前言 .NET 多平台应用 UI (.NET MAUI) 是一个跨平台框架&#xff0c;用于使用 C# 和 XAML 创…...

C++实现分布式网络通信框架RPC(3)--rpc调用端

目录 一、前言 二、UserServiceRpc_Stub 三、 CallMethod方法的重写 头文件 实现 四、rpc调用端的调用 实现 五、 google::protobuf::RpcController *controller 头文件 实现 六、总结 一、前言 在前边的文章中&#xff0c;我们已经大致实现了rpc服务端的各项功能代…...

树莓派超全系列教程文档--(61)树莓派摄像头高级使用方法

树莓派摄像头高级使用方法 配置通过调谐文件来调整相机行为 使用多个摄像头安装 libcam 和 rpicam-apps依赖关系开发包 文章来源&#xff1a; http://raspberry.dns8844.cn/documentation 原文网址 配置 大多数用例自动工作&#xff0c;无需更改相机配置。但是&#xff0c;一…...

2021-03-15 iview一些问题

1.iview 在使用tree组件时&#xff0c;发现没有set类的方法&#xff0c;只有get&#xff0c;那么要改变tree值&#xff0c;只能遍历treeData&#xff0c;递归修改treeData的checked&#xff0c;发现无法更改&#xff0c;原因在于check模式下&#xff0c;子元素的勾选状态跟父节…...

从零开始打造 OpenSTLinux 6.6 Yocto 系统(基于STM32CubeMX)(九)

设备树移植 和uboot设备树修改的内容同步到kernel将设备树stm32mp157d-stm32mp157daa1-mx.dts复制到内核源码目录下 源码修改及编译 修改arch/arm/boot/dts/st/Makefile&#xff0c;新增设备树编译 stm32mp157f-ev1-m4-examples.dtb \stm32mp157d-stm32mp157daa1-mx.dtb修改…...

浅谈不同二分算法的查找情况

二分算法原理比较简单&#xff0c;但是实际的算法模板却有很多&#xff0c;这一切都源于二分查找问题中的复杂情况和二分算法的边界处理&#xff0c;以下是博主对一些二分算法查找的情况分析。 需要说明的是&#xff0c;以下二分算法都是基于有序序列为升序有序的情况&#xf…...

全面解析各类VPN技术:GRE、IPsec、L2TP、SSL与MPLS VPN对比

目录 引言 VPN技术概述 GRE VPN 3.1 GRE封装结构 3.2 GRE的应用场景 GRE over IPsec 4.1 GRE over IPsec封装结构 4.2 为什么使用GRE over IPsec&#xff1f; IPsec VPN 5.1 IPsec传输模式&#xff08;Transport Mode&#xff09; 5.2 IPsec隧道模式&#xff08;Tunne…...

【HarmonyOS 5 开发速记】如何获取用户信息(头像/昵称/手机号)

1.获取 authorizationCode&#xff1a; 2.利用 authorizationCode 获取 accessToken&#xff1a;文档中心 3.获取手机&#xff1a;文档中心 4.获取昵称头像&#xff1a;文档中心 首先创建 request 若要获取手机号&#xff0c;scope必填 phone&#xff0c;permissions 必填 …...

大语言模型(LLM)中的KV缓存压缩与动态稀疏注意力机制设计

随着大语言模型&#xff08;LLM&#xff09;参数规模的增长&#xff0c;推理阶段的内存占用和计算复杂度成为核心挑战。传统注意力机制的计算复杂度随序列长度呈二次方增长&#xff0c;而KV缓存的内存消耗可能高达数十GB&#xff08;例如Llama2-7B处理100K token时需50GB内存&a…...

Python ROS2【机器人中间件框架】 简介

销量过万TEEIS德国护膝夏天用薄款 优惠券冠生园 百花蜂蜜428g 挤压瓶纯蜂蜜巨奇严选 鞋子除臭剂360ml 多芬身体磨砂膏280g健70%-75%酒精消毒棉片湿巾1418cm 80片/袋3袋大包清洁食品用消毒 优惠券AIMORNY52朵红玫瑰永生香皂花同城配送非鲜花七夕情人节生日礼物送女友 热卖妙洁棉…...

#Uniapp篇:chrome调试unapp适配

chrome调试设备----使用Android模拟机开发调试移动端页面 Chrome://inspect/#devices MuMu模拟器Edge浏览器&#xff1a;Android原生APP嵌入的H5页面元素定位 chrome://inspect/#devices uniapp单位适配 根路径下 postcss.config.js 需要装这些插件 “postcss”: “^8.5.…...