【C++】位域

位域

基础语法:

struct 结构体名 {
    数据类型 成员名 : 位数;
    数据类型 成员名 : 位数;
};

示例:

#include <iostream>

struct Flags {
    unsigned int a : 1; // 占1位
    unsigned int b : 2; // 占2位
    unsigned int c : 5; // 占5位
};

int main() {
    Flags f = {1, 3, 17};
    std::cout << f.a << " " << f.b << " " << f.c << std::endl; // 输出:1 3 17
    return 0;
}
 注意:
  • b 占 2 位,只能表示 0~3;
  • 如果你赋值超出了可表示的范围,会出现未定义行为。

 

 

例子1

#include <stdio.h>

// 1. 基本位域结构
struct BasicBitField {
    unsigned int flag1 : 1;    // 占用1位,值为0或1
    unsigned int flag2 : 1;    // 占用1位
    unsigned int value : 4;    // 占用4位,值范围0-15
    unsigned int reserved : 2; // 占用2位,保留字段
};

// 2. 寄存器映射示例
struct Register {
    unsigned int enable : 1;      // 使能位
    unsigned int mode : 2;        // 模式选择(0-3)
    unsigned int priority : 3;    // 优先级(0-7)
    unsigned int reserved1 : 2;   // 保留位
    unsigned int status : 8;      // 状态字段
    unsigned int reserved2 : 16;  // 剩余保留位
};

// 3. 网络协议头部示例
struct IPHeader {
    unsigned int version : 4;        // IP版本
    unsigned int header_length : 4;  // 头部长度
    unsigned int type_of_service : 8; // 服务类型
    unsigned int total_length : 16;   // 总长度
    unsigned int identification : 16; // 标识
    unsigned int flags : 3;          // 标志位
    unsigned int fragment_offset : 13; // 片偏移
};

// 4. 日期时间压缩存储
struct CompactDateTime {
    unsigned int second : 6;  // 秒 (0-59)
    unsigned int minute : 6;  // 分 (0-59)
    unsigned int hour : 5;    // 时 (0-23)
    unsigned int day : 5;     // 日 (1-31)
    unsigned int month : 4;   // 月 (1-12)
    unsigned int year : 6;    // 年 (相对于某基准年)
};

// 5. 状态标志集合
struct StatusFlags {
    unsigned int is_ready : 1;
    unsigned int is_busy : 1;
    unsigned int has_error : 1;
    unsigned int is_connected : 1;
    unsigned int debug_mode : 1;
    unsigned int test_mode : 1;
    unsigned int : 2;  // 未命名位域,用于对齐
};

// 6. 混合数据类型位域
struct MixedBitField {
    signed int temperature : 12;    // 有符号温度值 (-2048 到 2047)
    unsigned int humidity : 8;      // 无符号湿度值 (0-255)
    unsigned int sensor_id : 4;     // 传感器ID (0-15)
    unsigned int battery_level : 8; // 电池电量 (0-255)
};

int main() {
    // 基本使用
    struct BasicBitField bf = {0};
    bf.flag1 = 1;
    bf.flag2 = 0;
    bf.value = 12;  // 最大15
    
    printf("基本位域示例:\n");
    printf("flag1: %u, flag2: %u, value: %u\n", 
           bf.flag1, bf.flag2, bf.value);
    printf("结构体大小: %lu 字节\n\n", sizeof(bf));
    
    // 寄存器操作示例
    struct Register reg = {0};
    reg.enable = 1;
    reg.mode = 2;
    reg.priority = 5;
    reg.status = 0xFF;
    
    printf("寄存器操作示例:\n");
    printf("enable: %u, mode: %u, priority: %u, status: 0x%02X\n",
           reg.enable, reg.mode, reg.priority, reg.status);
    printf("寄存器大小: %lu 字节\n\n", sizeof(reg));
    
    // 压缩日期时间
    struct CompactDateTime dt = {0};
    dt.year = 24;    // 2024年(假设基准年为2000)
    dt.month = 12;
    dt.day = 25;
    dt.hour = 15;
    dt.minute = 30;
    dt.second = 45;
    
    printf("压缩日期时间:\n");
    printf("日期: 20%02u-%02u-%02u %02u:%02u:%02u\n",
           dt.year, dt.month, dt.day, dt.hour, dt.minute, dt.second);
    printf("日期时间结构大小: %lu 字节\n\n", sizeof(dt));
    
    // 状态标志
    struct StatusFlags flags = {0};
    flags.is_ready = 1;
    flags.is_connected = 1;
    flags.debug_mode = 0;
    
    printf("状态标志:\n");
    printf("ready: %u, busy: %u, error: %u, connected: %u\n",
           flags.is_ready, flags.is_busy, flags.has_error, flags.is_connected);
    printf("标志结构大小: %lu 字节\n\n", sizeof(flags));
    
    // 混合数据类型
    struct MixedBitField sensor = {0};
    sensor.temperature = -50;  // 负温度
    sensor.humidity = 65;
    sensor.sensor_id = 3;
    sensor.battery_level = 85;
    
    printf("传感器数据:\n");
    printf("温度: %d, 湿度: %u%%, 传感器ID: %u, 电池: %u%%\n",
           sensor.temperature, sensor.humidity, 
           sensor.sensor_id, sensor.battery_level);
    printf("传感器数据大小: %lu 字节\n\n", sizeof(sensor));
    
    // 位域的内存布局(平台相关)
    printf("内存地址信息:\n");
    printf("bf地址: %p\n", (void*)&bf);
    printf("reg地址: %p\n", (void*)&reg);
    
    // 演示位域溢出
    printf("位域溢出示例:\n");
    bf.value = 20;  // 超过4位能表示的最大值15
    printf("设置value=20后,实际值: %u (被截断为: %u)\n", 
           20, bf.value);
    
    return 0;
}

/* 
输出说明:
1. 位域会自动进行位打包,节省内存空间
2. 超出位数范围的值会被自动截断
3. 实际内存布局依赖于编译器和平台
4. 位域主要用于底层编程、寄存器操作、协议解析等场景
*/

 

posted @ 2021-02-07 22:22  苏格拉底的落泪  阅读(132)  评论(0)    收藏  举报