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

C语言基础系列【17】位域

博主介绍:程序喵大人

  • 35- 资深C/C++/Rust/Android/iOS客户端开发
  • 10年大厂工作经验
  • 嵌入式/人工智能/自动驾驶/音视频/游戏开发入门级选手
  • 《C++20高级编程》《C++23高级编程》等多本书籍著译者
  • 更多原创精品文章,首发gzh,见文末
  • 👇👇记得订阅专栏,以防走丢👇👇
    😃C++基础系列专栏
    😃C语言基础系列
    😃C++大佬养成攻略

位域(Bit-field)是一种特殊的数据结构,通过位域,开发者在结构体中定义成员时,可以指定成员所占用的位数,而不是按照数据类型默认的字节数来分配空间。这种特性使得位域可以精确控制内存的使用。

下面详细介绍。

基本概念

位域是一种在结构体中定义成员时,指定成员所占用的位数的方法。这种定义方式使得结构体成员可以只占用小于一个字节的空间,有效地节省了内存。

位域通常用于表示布尔值、标志位、状态码等只需要少量位来表示的数据。

位域的定义形式如下:

struct {
type [member_name] : width;
};

其中,type是指定位域的数据类型,可以是intunsigned intsigned int等整数类型,也可以是枚举类型。member_name是位域的名称,width是指定位域所占用的位数。

使用示例

下面是一个简单的位域使用示例:

#include <stdio.h>

struct {
unsigned int widthValidated : 1;
unsigned int heightValidated : 1;
} status;

int main() {
    status.widthValidated = 1; // 宽度验证通过
    status.heightValidated = 0; // 高度验证未通过

    printf("Width validated: %u\n", status.widthValidated);
    printf("Height validated: %u\n", status.heightValidated);

    return 0;
}

status的结构体,包含两个位域成员:widthValidatedheightValidated,它们各占用1位。

内存布局

位域成员在内存中是按位分配的,而不是按字节分配。如果一个位域成员所占用的位数不足以填满一个字节,那么剩余的位将被填充为0。

下面示例展示了位域在内存中的布局:

#include <stdio.h>

struct packed_struct {
unsigned int f1 : 1;
unsigned int f2 : 1;
unsigned int f3 : 1;
unsigned int f4 : 1;
unsigned int type : 4;
unsigned int my_int : 9;
};

int main() {
    struct packed_struct pack;
    pack.f1 = 1;
    pack.f2 = 0;
    pack.f3 = 1;
    pack.f4 = 0;
    pack.type = 7;
    pack.my_int = 255;

    printf("f1: %u\n", pack.f1);
    printf("f2: %u\n", pack.f2);
    printf("f3: %u\n", pack.f3);
    printf("f4: %u\n", pack.f4);
    printf("type: %u\n", pack.type);
    printf("my_int: %u\n", pack.my_int);
    printf("pack: %lu\n", sizeof(pack));

    return 0;
}

packed_struct结构体包含六个位域成员。这些成员在内存中的布局如下:

  • f1f2f3f4各占用1位,共占用4位。
  • type占用4位。
  • my_int占用9位。

因此,packed_struct结构体总共占用17位,但在大多数系统中,它会被分配到四个字节(32位)的内存空间中,因为内存分配通常是以字节为单位的。

注意事项

  1. 位域宽度的限制:位域的宽度不能超过其数据类型的大小。例如,unsigned int类型通常是32位,因此其位域的最大宽度不能超过32位。
  2. 内存对齐:虽然位域可以节省内存,但它可能会导致内存对齐问题。编译器可能会在位域之间插入填充字节,确保结构体成员满足对齐要求。这可能会影响位域的实际内存布局。
  3. 跨平台差异:位域的行为在不同的编译器和平台上可能有所不同。因此,在编写可移植代码时,应谨慎使用位域。
  4. 访问效率:由于位域成员是按位访问的,因此访问位域可能比访问普通结构体成员更慢。这是因为编译器需要将位域值转换为整数值或反之。

实际应用

例如:

  • 硬件寄存器编程:在处理硬件寄存器时,位域可以用来表示寄存器的各个位字段。
  • 网络通信协议:在网络通信协议中,位域可以用来表示协议头中的各个标志位和选项。
  • 嵌入式系统开发:在嵌入式系统开发中,位域经常用于表示设备的状态、配置选项等。

示例:使用位域解析网络协议头

下面是一个使用位域解析简单网络协议头的示例:

#include <stdio.h>

struct ip_header {
unsigned int version : 4;      // 版本号,占4位
unsigned int header_length : 4; // 头部长度,占4位
unsigned int tos : 8;           // 服务类型,占8位
unsigned int total_length : 16; // 总长度,占16位
unsigned int identification : 16; // 标识,占16位
unsigned int flags : 3;         // 标志位,占3位
unsigned int fragment_offset : 13; // 片偏移,占13位
unsigned int ttl : 8;           // 生存时间,占8位
unsigned int protocol : 8;      // 协议类型,占8位
unsigned int checksum : 16;      // 校验和,占16位
unsigned int source_ip : 32;    // 源IP地址,占32位
unsigned int destination_ip : 32; // 目的IP地址,占32位
};

int main() {
    // 假设这里有一个从网络接收到的IP头部数据
    unsigned char ip_header_data[20] = {
    // 这里填充实际的IP头部数据
};

    struct ip_header *ip_header = (struct ip_header *)ip_header_data;

    printf("Version: %u\n", ip_header->version);
    printf("Header Length: %u\n", ip_header->header_length);
    printf("TOS: %u\n", ip_header->tos);
    // 继续打印其他字段...

    return 0;
}

这里定义了一个ip_header结构体,它使用位域来表示IP头部的各个字段。通过强制类型转换,可以将接收到的IP头部数据转换为ip_header结构体指针,并方便地访问各个字段的值。

练习

  • 可以看懂相关代码并理解即可,平时用到的很少。

码字不易,欢迎大家点赞关注评论,谢谢!


C++训练营

专为校招、社招3年工作经验的同学打造的1V1 C++训练营,量身定制学习计划、每日代码review,简历优化,面试辅导,已帮助多名学员获得offer!训练营介绍

相关文章:

  • 【NLP 30、大模型中的 ”Token“】
  • Tagr 5 for Mac v5.8.0 [MAS] 音频标签编辑工具 支持M、Intel芯片
  • 4.万事开头难—第一个Java程序
  • 使用Maven搭建Spring Boot框架
  • DH法建立6自由度机械臂正运动学模型
  • python (第九章 项目开发阶段)
  • explore与explode词源故事
  • 高频面试题(含笔试高频算法整理)基本总结回顾16
  • 992. K 个不同整数的子数组
  • nginx+keepalived实现高可用负载均衡
  • Python中文自然语言处理库SnowNLP
  • 建筑兔零基础人工智能自学记录34|深度学习与神经网络2
  • 【单点登录】SSO单点登录sa-token接入流程详解
  • Linux服务器Ubuntu系统环境中安装Jupyter Notebook并且配置内核以便在网页端调用
  • TCP通讯与基于C#TCP通讯,跨窗收发消息Demo
  • JavaScript 内存管理:利用数据结构优化内存使用
  • Linux系统中proc是做什么的?
  • MySQL索引深度剖析:从数据结构到实际应用
  • 【MySQL篇】数据类型
  • 01 计算机系统层次结构和冯·诺依曼计算机
  • 做搜狗网站优化首页软/市场营销实际案例
  • 老师做家教的网站/googleplay官网
  • 建设网站前的市场分析包括哪些内容/怎么做市场推广
  • 网站开发 调试/网络营销渠道
  • 手机网站设计报告模板/适合推广的app有哪些
  • 武汉哪些网站建设/免费搭建网站