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

85、【OS】【Nuttx】【番外】gcc 关键字:位域(上)

【声明】本博客所有内容均为个人业余时间创作,所述技术案例均来自公开开源项目(如Github,Apache基金会),不涉及任何企业机密或未公开技术,如有侵权请联系删除

背景

接之前 blog
【OS】【Nuttx】【启动】栈溢出保护:asm 关键字(上)
【OS】【Nuttx】【启动】栈溢出保护:asm 关键字(下)
分析了 asm, __asm__ 和 __asm 等关键字的概念和用法,下面最后再补充下 gcc 相关的关键字细节

gcc 关键字

上篇 blog 【OS】【Nuttx】【启动】栈溢出保护:asm 关键字(下) 提到了关键字类型 c_common_resword
在这里插入图片描述

这里涉及到了位域的知识点,下面来详细分析下

位域

在 C 语言中,使用位域是一种节省内存空间的技术,比较适合结构体中某些字段只需要少量比特位的情况,比如下面这里,rid : 16 表示 rid 字段占用了 16 个 bit 位,disable : 32 表示 disable 字段占用了 32 个 bit 位

在这里插入图片描述
下面来分析下使用位域这种方法的好处:

  • 节省内存:如果一个字段只需要几个 bit 就能表示(比如状态标志、枚举值等),使用完整的 int 类型会浪费很多内存,而使用位域可以让多个字段共享同一个整数类型的存储空间,比如这里的 rid,如果用完整的 int 类型,4 个字节最大值 2147483647,足足有 21 亿个保留关键字 rid,很明显保留关键字用不了这么多(现在连 1000 个都没有),所以使用位域是比较好的选择

有好处就会有坏处,两个比较明显的:

  • 不能取地址:位域成员不能使用 & 运算符取地址
  • 性能代价:访问位域字段可能比普通字段慢,因为需要进行掩码和移位操作

所以总结一下,如果在意内存使用效率或需要精确控制数据布局(比如编译器,操作系统,嵌入式等场景)的底层基础设施,可以使用位域;否则,在一般应用层编程中可以不用它(因为内存很充足,随便用)

另外要补充的是,使用位域并不会节省下结构体对齐的内存,只是将原有的数据类型给缩小了,而结构体对齐要填充的内存还是会存在的,比如下面这个例子(其实就是 gcc 源码的结构体)

// main.c
#include <stdio.h>enum RidType
{RID_TEST_1 = 0U,RID_TEST_2,
};struct ResWordsType {const const char *const word;enum RidType rid : 16;const unsigned int disable : 32;
};int main(void) {printf("%ld\n", sizeof(struct ResWordsType));return 0;
}

在 x86_64 环境上,指针 word 占 8 个字节,枚举类型 rid 使用位域占 2 个字节,disable 占 4 个字节,所以理论上有效内容总共是 8 + 2 + 4 = 14 字节

在 x86_64 环境上编译,终端输入命令并运行,可以看到实际这个结构体占了 16 个字节
在这里插入图片描述

这里面就涉及到结构体对齐的规则:整个结构体的大小必须是其最大成员对齐要求的倍数,这里结构体 ResWordsType 里最大的成员是 word 指针,占 8 个字节,那么结构体就必须按照 8 字节进行对齐,所以有效内容 14 字节还需向上对齐 2 个字节,到 16 字节

可以看到,位域并不能把结构体对齐要填充的字节省下来,那么,如果这里不用位域呢?还是同样的代码,只不过把位域省掉了

// main.c
#include <stdio.h>enum RidType
{RID_TEST_1 = 0U,RID_TEST_2,
};struct ResWordsType {const const char *const word;enum RidType rid;const unsigned int disable;
};int main(void) {printf("%ld\n", sizeof(struct ResWordsType));return 0;
}

在 x86_64 环境上,word 指针占 8 字节,枚举成员 rid 占 4 字节,disable 成员占 4 字节,理论上刚好 16 字节,都不用填充字节了

终端输入编译命令,运行,可以看到确实也是 16 字节
在这里插入图片描述

那么问题来了,刚才说了用位域可以节省内存,但现在用位域和不用位域,占的空间大小一样,那用位域还有什么意义呢?

这个问题,下篇 blog 再解答

http://www.dtcms.com/a/305220.html

相关文章:

  • 影翎Antigravity将发布全球首款全景无人机,8月开启公测招募
  • Leetcode 08 java
  • Linux | 文件权限
  • 面试刷题平台项目总结
  • ERROR c.a.c.n.c.NacosPropertySourceBuilder
  • 对讲机该怎么选?2025建议买的对讲机品牌
  • 并查集介绍及典型应用和编程题
  • 专线与专线之间的区别
  • Docker初学者需要了解的几个知识点(二):Docker、容器镜像
  • 2025年运维相关面试题
  • 前端手写贴
  • 北方公司面试记录
  • A1324LLHLX-T Allegro:高精度线性霍尔效应传感器 ±1%精度+4.5mV/G超高灵敏度
  • python优秀案例:基于机器学习算法的景区旅游评论数据分析与可视化系统,技术使用django+lstm算法+朴素贝叶斯算法+echarts可视化
  • 域名常见问题集(九)——域名市场介绍
  • VNC和RPC加固措施
  • Redis+JWT 认证管理最佳实践
  • MybatisPlus-20.插件功能-通用分页实体与MP转换
  • 推动技术的发展和创新:编程是IT行业中最为基础和核心的技能之一
  • 计算机网络五层模型
  • echarts(4.9.0)x轴标签过长,截取指定长度显示三个点,鼠标放上去显示完整标签示例
  • “影子插桩”:利用 LLVM 在二进制层面对 dlsym 调用做无痕监控(C/C++实现)
  • 前端基础之《Vue(26)—Vue3两种语法范式》
  • C++(面向对象之继承、多态)
  • C++20协程实战:高效网络库、手机终端、多媒体开发开发指南
  • 嵌入向量与向量数据库:AI时代的语义搜索革命
  • 【Git】分支
  • 前端接入DeepSeek
  • 数据结构(6)单链表算法题(下)
  • 如何使用Spring AI框架开发mcp接口并发布成微服务