位域使用注意

本文探讨了C语言中的位域操作在编译成汇编代码后的复杂过程,指出其潜在风险,如在读取存储单元后被中断服务函数修改。举例说明了位域设置的具体汇编步骤,并强调了这种操作可能导致的程序异常问题,不推荐在对实时性和安全性要求高的场景下使用位域。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 位域使用时虽然语句比较简洁,但是编译成汇编之后,其实比较麻烦,并且存在一定的风险。

例如:

C语言:   PWMx->TBCTL_b.HSPCLKDIV = 0;    // 将PWMx->TBCTL寄存器的7,8,9位写0

汇编 :

0x00000F60 6801      LDR      r1,[r0,#0x00]       ; 将r0地址偏移0个地址之后存储的值赋值给r1寄存器 ,即 r1 =  PWMx->TBCTL

0x00000F3E 2207      MOVS  r2,#0x07            ; 将r2寄存器等于7,即 r2= 0x07   

0x00000F40 01D2      LSLS     r2,r2,#7             ; 将r2寄存器等于r2寄存器左移7位,即 r2 = r2<<7  = 0x0380 

0x00000F42 4391      BICS     r1,r1,r2             ; 将r1寄存器等于r1寄存器第7,8,9位清零, 参考 BIC(位清除)指令

0x00000F44 6001      STR      r1,[r0,#0x00]      ;将r0偏移0个地址中的值放到以r1中的值为地址的存储单元去。

从上面例子可以看出位域操作某个存储单元的某一位或者几位都是通过先把该单元读取出来保存,再把要设置的位清空再赋值,最后把该值再赋值给存储单元;

风险就在如果程序刚把存储单元(数据0x04)读取保存之后,有其他中断响应之后跳转到中断服务函数中也对该存储单元进行修改(将最高位置1),执行完服务函数之后继续执行设置位复制,再把值赋给存储单元(数据0x04),这时在中断中对存储单元写的无效;

不推荐使用位域,不然程序会遇到bug(大部分时候程序是正常跑的,有时会异常),亲身经历这种bug查到怀疑人生。

### 结构体使用方法与注意事项 在C/C++中,结构体(bit field)是一种允许以为单指定成员所占内存长度的机制。这种特性常用于嵌入式开发、网络协议字段定义以及状态量管理等场景,能够显著节省内存资源[^4]。 以下是一个典型的结构体示例及其用法: ```c #include <stdio.h> struct BitField { unsigned int flag1 : 1; // 占用1 unsigned int flag2 : 1; // 占用1 unsigned int value : 4; // 占用4 }; int main() { struct BitField bf; bf.flag1 = 1; // 设置flag1为1 bf.flag2 = 0; // 设置flag2为0 bf.value = 15; // 设置value为15 (二进制1111) printf("flag1: %u\n", bf.flag1); printf("flag2: %u\n", bf.flag2); printf("value: %u\n", bf.value); return 0; } ``` #### 注意事项 1. **大小限制**:成员的大小由其类型决定。例如,`unsigned int`类型的可以最多占用32(取决于系统架构)。如果超出范围,编译器可能会报错或产生未定义行为[^4]。 2. **字节对齐**:即使使用,编译器仍可能根据默认对齐规则进行填充。可以通过`#pragma pack`指令强制设置对齐方式[^3]。 3. **跨平台兼容性**:不同编译器和平台对的实现可能存在差异,因此在设计跨平台代码时需格外小心[^4]。 4. **读写效率**:由于涉及按操作,访问速度可能较普通变量慢。因此,在性能敏感的场景下需权衡使用### 示例解析 在上述代码中: - `flag1` 和 `flag2` 各占用1,适合表示布尔值。 - `value` 占用4,适合存储0到15之间的整数值。 - 整个结构体的实际大小取决于编译器对的实现细节和对齐规则。 ### 内存布局 对于的内存布局,编译器通常会将连续的成员打包到同一个存储单元中。例如,在32系统上,上述结构体可能被分配在一个`unsigned int`中,具体布局如下: - 第0:`flag1` - 第1:`flag2` - 第2至第5:`value` 若后续成员无法完全放入当前存储单元,则会开启新的存储单元。 ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值