news 2026/3/8 10:44:48

C语言位运算

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
C语言位运算

位运算的分类与详细说明

一、基本位运算

1、按位与(&)

功能:两个操作数对应位都为1时,结果位才为1

嵌入式应用:

• 掩码操作:提取特定位的值

// 提取低4位 uint8_t value = 0x5A; uint8_t lower_nibble = value & 0x0F; // 结果为0x0A

• 清除特定位:将指定位设为0

// 清除第3位 value &= ~(1 << 3);

2、按位或(|)

功能:两个操作数对应位有一个为1时,结果位就为1

嵌入式应用:

• 设置特定位:将指定位设为1

// 设置第5位 uint8_t config = 0x20; config |= (1 << 5); // 确保第5位为1

• 合并多个位字段

// 合并高低4位 uint8_t high = 0xA0, low = 0x0B; uint8_t combined = (high & 0xF0) | (low & 0x0F); // 结果为0xAB

3、按位异或(^)

功能:两个操作数对应位不同时,结果位为1

嵌入式应用:

• 特定位翻转

// 翻转第2位和第3位 uint8_t data = 0x35; data ^= (0x3 << 2); // 翻转第2-3位

• 不使用临时变量交换值

// 交换两个变量的值(无临时变量) a ^= b; b ^= a; a ^= b;

4、按位取反(~)

功能:将操作数的每一位取反

嵌入式应用:

• 创建掩码

// 创建低4位掩码 uint8_t mask = ~0x0F; // 结果为0xF0

• 配合其他位运算使用

// 清除多个位 uint8_t status = 0xFF; status &= ~((1 << 0) | (1 << 3) | (1 << 7)); // 清除第0、3、7位

二、移位运算

1、左移(<<)

功能:将操作数的所有位向左移动指定位数,右侧空位补0

嵌入式应用:

• 乘以2的幂次

// 快速乘以4 uint32_t value = 25; uint32_t quadrupled = value << 2; // 结果为100

• 创建位掩码

// 创建第n位掩码 #define BIT(n) (1 << (n))

• 位字段定位

// 设置位字段(第3-5位) uint32_t reg = 0; uint32_t field_value = 0x5; // 二进制101 reg |= (field_value << 3); // 将101放在第3-5位

2、右移(>>)

功能:将操作数的所有位向右移动指定位数 注意:对于有符号数,右移行为取决于编译器(算术右移或逻辑右移)

嵌入式应用:

• 除以2的幂次

// 快速除以8 uint32_t value = 100; uint32_t divided = value >> 3; // 结果为12

• 提取位字段

// 提取第4-7位 uint32_t data = 0x5A; uint32_t field = (data >> 4) & 0x0F; // 结果为0x05

三、复合位运算

1、位字段操作 结合多种位运算实现复杂的位操作:

// 读取第n-m位字段 uint32_t read_bitfield(uint32_t reg, uint8_t start, uint8_t length) { uint32_t mask = (1 << length) - 1; return (reg >> start) & mask; }
// 写入第n-m位字段 void write_bitfield(uint32_t *reg, uint8_t start, uint8_t length, uint32_t value) { uint32_t mask = (1 << length) - 1; *reg &= ~(mask << start); // 清除目标位字段 *reg |= (value & mask) << start; // 写入新值 }

四、嵌入式系统中的实际应用实例

1、硬件寄存器配置 GPIO配置示例

// STM32 GPIO配置 typedef struct { volatile uint32_t MODER; // 模式寄存器 volatile uint32_t OTYPER; // 输出类型寄存器 volatile uint32_t OSPEEDR; // 输出速度寄存器 volatile uint32_t PUPDR; // 上拉/下拉寄存器 } GPIO_TypeDef;
// 配置PA5为推挽输出,高速模式 void GPIO_Config(void) { GPIO_TypeDef *GPIOA = (GPIO_TypeDef*)0x40020000; // 设置PA5为输出模式 (MODER5 = 0b01) GPIOA->MODER &= ~(0x3 << 10); // 清除MODER5 GPIOA->MODER |= (0x1 << 10); // 设置MODER5为输出 // 设置推挽输出 (OTYPER5 = 0) GPIOA->OTYPER &= ~(1 << 5); // 设置高速模式 (OSPEEDR5 = 0b10) GPIOA->OSPEEDR &= ~(0x3 << 10); GPIOA->OSPEEDR |= (0x2 << 10); }
// 配置NVIC中断 void NVIC_Config(void) { // 使能EXTI0中断(位置6) NVIC->ISER[0] |= (1 << 6); // 设置优先级(位字段操作) uint8_t priority = 0x05; // 优先级5 NVIC->IP[6] = (priority << 4); // 优先级寄存器使用高4位 }

2、数据压缩与编码 状态标志打包

// 多个状态标志打包到一个字节中 typedef union { struct { uint8_t error_flag : 1; // 位0:错误标志 uint8_t data_ready : 1; // 位1:数据就绪 uint8_t tx_complete : 1; // 位2:发送完成 uint8_t rx_overflow : 1; // 位3:接收溢出 uint8_t reserved : 4; // 位4-7:保留 } bits; uint8_t byte; } status_reg_t;
// 使用示例 status_reg_t status; status.bits.data_ready = 1; status.bits.tx_complete = 0; if (status.byte & 0x02) { // 检查数据就绪标志 // 处理数据 } // 将多个小数值打包到32位整数中 uint32_t pack_data(uint8_t a, uint8_t b, uint8_t c, uint8_t d) { return (a << 24) | (b << 16) | (c << 8) | d; } void unpack_data(uint32_t packed, uint8_t *a, uint8_t *b, uint8_t *c, uint8_t *d) { *a = (packed >> 24) & 0xFF; *b = (packed >> 16) & 0xFF; *c = (packed >> 8) & 0xFF; *d = packed & 0xFF; }

3、通信协议处理

// SPI软件实现(位碰撞) uint8_t spi_transfer(uint8_t data) { uint8_t i; for (i = 0; i < 8; i++) { // 设置MOSI(最高位先发送) if (data & 0x80) { MOSI_HIGH(); } else { MOSI_LOW(); } // 产生时钟上升沿 SCK_HIGH(); // 读取MISO data <<= 1; if (MISO_READ()) { data |= 0x01; } // 产生时钟下降沿 SCK_LOW(); } return data; }
// CRC8计算 uint8_t crc8(const uint8_t *data, uint32_t length) { uint8_t crc = 0xFF; uint32_t i, j; for (i = 0; i < length; i++) { crc ^= data[i]; for (j = 0; j < 8; j++) { if (crc & 0x80) { crc = (crc << 1) ^ 0x07; // CRC8多项式 } else { crc <<= 1; } } } return crc; }

4、性能优化技巧

// 使用移位优化乘除法 uint32_t fast_multiply(uint32_t a, uint32_t b) { // 如果b是2的幂次,使用移位 if ((b & (b - 1)) == 0) { uint32_t shift = 0; while (b > 1) { b >>= 1; shift++; } return a << shift; } return a * b; // 否则使用普通乘法 } uint32_t fast_divide(uint32_t a, uint32_t b) { // 如果b是2的幂次,使用移位 if ((b & (b - 1)) == 0) { uint32_t shift = 0; while (b > 1) { b >>= 1; shift++; } return a >> shift; } return a / b; // 否则使用普通除法 }
// 预计算的位反转查找表 static const uint8_t bit_reverse_table[256] = { 0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0, // ... }; uint8_t fast_bit_reverse(uint8_t x) { return bit_reverse_table[x]; }

五、最佳实践与注意事项

1、可读性考虑

// 不好的写法 reg |= 0x88;
// 好的写法 - 使用宏或枚举定义位位置 #define TX_ENABLE (1 << 3) #define RX_ENABLE (1 << 7) reg |= TX_ENABLE | RX_ENABLE;

2、移植性考虑

// 避免对符号数进行位运算 int32_t signed_value = -1; // uint32_t result = signed_value >> 1; // 移植性差
// 使用无符号数进行位运算 uint32_t unsigned_value = (uint32_t)signed_value; uint32_t result = unsigned_value >> 1;

3、原子性考虑

在多任务或中断环境中,对共享资源的位操作应该是原子的:

// 使用原子操作或关中断保护关键位操作 __disable_irq(); critical_reg |= CRITICAL_BIT; __enable_irq();
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/3/8 2:21:30

EmotiVoice能否生成带有地方戏曲腔调的特色语音?

EmotiVoice能否生成带有地方戏曲腔调的特色语音&#xff1f; 在数字内容不断演进的今天&#xff0c;AI语音合成早已不再满足于“能说话”——用户期待的是有性格、有情绪、有文化底色的声音。尤其是在中华文化的语境下&#xff0c;地方戏曲那独特的咬字、行腔与节奏&#xff0c…

作者头像 李华
网站建设 2026/2/25 17:26:35

Docker 权限问题:为什么容器里读不到文件?

Docker 权限问题&#xff1a;为什么容器里读不到文件&#xff1f;这是 Docker 使用过程中非常典型、但极具迷惑性的问题之一&#xff1a;文件明明存在&#xff0c;路径也没写错&#xff0c;但容器里就是读不到、写不了&#xff0c;甚至直接 Permission denied。本文将从 Linux …

作者头像 李华
网站建设 2026/2/25 1:58:42

COLMAP三维重建性能瓶颈突破:5个Eigen矩阵优化技巧实战指南

COLMAP三维重建性能瓶颈突破&#xff1a;5个Eigen矩阵优化技巧实战指南 【免费下载链接】colmap COLMAP - Structure-from-Motion and Multi-View Stereo 项目地址: https://gitcode.com/GitHub_Trending/co/colmap 在计算机视觉领域&#xff0c;COLMAP作为业界领先的三…

作者头像 李华
网站建设 2026/2/13 7:54:22

浏览器兼容性革命:Skyvern如何用模块化设计打破自动化壁垒

浏览器兼容性革命&#xff1a;Skyvern如何用模块化设计打破自动化壁垒 【免费下载链接】skyvern 项目地址: https://gitcode.com/GitHub_Trending/sk/skyvern 在企业级自动化工具领域&#xff0c;浏览器兼容性一直是困扰开发者的核心难题。不同内核的渲染差异、API支持…

作者头像 李华
网站建设 2026/3/2 18:03:22

ViVeTool GUI:Windows隐藏功能管理终极指南与完整教程

ViVeTool GUI&#xff1a;Windows隐藏功能管理终极指南与完整教程 【免费下载链接】ViVeTool-GUI Windows Feature Control GUI based on ViVe / ViVeTool 项目地址: https://gitcode.com/gh_mirrors/vi/ViVeTool-GUI 想要深度掌控Windows系统却苦于复杂的命令行操作&am…

作者头像 李华
网站建设 2026/3/4 0:51:35

分布式系统中一致性哈希的作用

一次扩容&#xff0c;缓存全崩&#xff1f;一致性哈希如何拯救分布式系统你只是加了一台服务器&#xff0c;结果整个缓存集群像失忆了一样。这是很多工程师都踩过的坑。 那天你信心满满地给缓存集群扩容了一台机器&#xff0c;准备迎接流量高峰。结果监控一片飘红&#xff1a; …

作者头像 李华