C语言结构体位域的使用技巧(联合体妙用)

C语言结构体位域的使用技巧

基本概念

  • 在C语言中,位域(Bit Fields)是一种数据结构,它允许程序员访问内存中的单个位。位域通常用于硬件编程,例如嵌入式系统开发,因为它们允许程序员直接访问和控制硬件寄存器的特定位。位域在不同的编译器和平台上可能会有不同的内存对齐和打包行为,因此在移植代码时需要小心。

基本语法

  • struct {
        unsigned int member1 : n1;
        unsigned int member2 : n2;
        // ... 可以继续添加更多的位域成员
    } yourStructName;
    
    • unsigned int 表示位域成员的数据类型,通常是 unsigned int,但也可以是 signed int_Bool
    • member1member2 是位域成员的名称。
    • : n1: n2 指定了每个成员所占用的位数,n1n2 是介于1到数据类型大小之间的整数。

    位域成员可以是无符号的或有符号的,取决于它们前面的关键字 unsignedsigned。如果省略了这些关键字,位域默认为无符号。

    位域成员的总位数不能超过它们所属的数据类型的大小。例如,如果使用 unsigned int(通常是32位),则所有位域成员的位数总和不能超过32位。

举例

  • #include <stdio.h>
    
    struct BitField {
        unsigned int is_enabled : 1;   // 占用1位
        unsigned int has_data   : 1;   // 占用1位
        unsigned int error_code : 6;   // 占用6位
        unsigned int mode       : 2;   // 占用2位
        unsigned int reserved   : 22;  // 占用22位,通常用于对齐或保留
    };
    
    int main() {
        struct BitField myBitField;
        myBitField.is_enabled = 1;
        myBitField.has_data = 0;
        myBitField.error_code = 31; // 只有最低6位会被使用
        myBitField.mode = 3;
    
        printf("is_enabled: %d\n", myBitField.is_enabled);
        printf("has_data: %d\n", myBitField.has_data);
        printf("error_code: %d\n", myBitField.error_code);
        printf("mode: %d\n", myBitField.mode);
    
        return 0;
    }
    

但是

  • 嵌入式一般在搞寄存器的时候会用到位域,像上面这个例子,但是我没法把 myBitField 这个结构体当成数值来用,除非用指针强转,但是这个行为存在危险性。那么怎么搞?嘿嘿,整个联合体就好了。

    typedef union {
        struct {
            unsigned int is_enabled : 1;   // 占用1位
        	unsigned int has_data   : 1;   // 占用1位
        	unsigned int error_code : 6;   // 占用6位
        	unsigned int mode       : 2;   // 占用2位
        	unsigned int reserved   : 22;  // 占用22位,通常用于对齐或保留
        } Bits;
        unsigned int  Value;
    } Super;
    

    联合体(union)的一个主要特性是它所有的成员都占用相同的内存位置。这意味着,你改结构体就是在改Value。给结构体赋完值以后,直接用Value就行!

### C语言的高低表示方法 在C语言中,用于将一个字节中的二进制划分为多个不同区,并指定每个区所占用的数。这有助于更高效地利用内存资源并简化某些类型的级操作。 #### 定义与基本语法 通过`struct`关键字可以创建包含的数据结构。每个成员后面跟上冒号以及该成员所需的具体比特数量: ```c struct bit_field { unsigned int flag : 1; // 占用1 unsigned int value : 7; // 占用7 }; ``` 上述代码片段展示了如何在一个名为`bit_field`的结构体内定义两个分别占据一和七长度的无符号整型变量[^4]。 #### 高低顺序及其影响 当涉及到具体硬件平台时,内部各字段的实际排列方式取决于编译器实现细节及目标架构特性。特别是对于多于一字节大小的情况而言,存在两种常见的序安排——最低有效(Least Significant Bit, LSB)优先和最高有效(Most Significant Bit, MSB)优先。 - **LSB优先**:意味着最右边的一被视作第零; - **MSB优先**:则相反,最左边的一作为起始置。 需要注意的是,在实际编程实践中,由于不同处理器可能遵循不同的字节序规则(即大端法Big Endian vs 小端法Little Endian),因此即使在同一平台上也可能观察到差异化的表现形式[^2]。 #### 实际案例分析 考虑如下例子来进一步理解这一点: ```c #include <stdio.h> struct bs { unsigned char a : 1; unsigned char b : 2; unsigned char c : 5; }; union { struct bs n; unsigned char n_char; } u; int main() { u.n.a = 1; u.n.b = 1; u.n.c = 1; printf("n_char=0x%.2x\n", u.n_char); } ``` 这段程序首先初始化了一个联合体实例`u`,其中包含了具有特定宽度约束的三个字符类型成员a、b 和 c 。接着设置这些成员各自的值均为1 ,最后打印出整个联合体作为一个整体来看待的结果 `n_char` 的十六进制表示形式。 假设当前环境下的编译器按照从低至高的顺序分配,则最终输出应为`0x1f`;反之如果是高向低调配的话,则会得到其他数值。然而确切的行为依赖于具体的编译工具链配置选项以及其他因素共同决定。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值