C语言之offsetof实现分析(九十一)

简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长!

优质专栏:Audio工程师进阶系列原创干货持续更新中……】🚀
优质专栏:多媒体系统工程师系列原创干货持续更新中……】🚀
优质视频课程:AAOS车载系统+AOSP14系统攻城狮入门实战课原创干货持续更新中……】🚀

人生格言: 人生从来没有捷径,只有行动才是治疗恐惧和懒惰的唯一良药.

更多原创,欢迎关注:Android系统攻城狮

欢迎关注Android系统攻城狮

🍉🍉🍉文章目录🍉🍉🍉

    • 🌻1.前言
    • 🌻2.C语言之offsetof介绍
    • 🌻3.代码实例
      • 🐓3.1 offsetof宏结构解析
      • 🐓3.2 计算结构体成员的偏移量
      • 🐓3.3 通过偏移量访问结构体成员
      • 🐓3.4 在动态分配的结构体数组中使用偏移量

🌻1.前言

本篇目的:C语言之offsetof实现分析

🌻2.C语言之offsetof介绍

  • C语言中的offsetof宏是一个非常有用的工具,它用于计算结构体中某个成员相对于结构体开头的偏移量。这个宏定义在头文件<stddef.h>中,它是C标准库的一部分。
  • offsetof宏的使用方法非常简单,它的原型如下:
offsetof(type, member);
  • 其中,type是一个结构体类型,membertype结构体中的一个成员。offsetof宏的返回值是member成员相对于type结构体开头的字节偏移量。
  • offsetof宏的实现通常依赖于编译器的特性,但一般情况下,它可以像下面这样实现:
#define offsetof(type, member) ((size_t)&(((type *)0)->member))
  • 这里,(type *)0将一个指向类型为type的结构的指针设置为地址0。这样做是合法的,因为offsetof宏不会解引用这个指针。然后,我们取member的地址,由于结构体的地址是0,所以member的地址就是member相对于结构体开头的偏移量。最后,我们将这个地址转换为size_t类型的值,这个值就是offsetof宏的返回值。
  • offsetof宏的一个常见用途是在实现泛型容器类时,比如C++的标准模板库(STL)中的vectorlistmap等容器。在这些容器中,我们通常需要获取元素类型中的某个成员的偏移量,以便在内存中正确地定位和访问这些成员。
  • 例如,假设我们有一个结构体MyStruct,它有两个成员ab
struct MyStruct {int a;char b;
};
  • 我们可以使用offsetof宏来获取成员ab相对于结构体开头的偏移量:
size_t offset_a = offsetof(MyStruct, a);
size_t offset_b = offsetof(MyStruct, b);
  • 在这个例子中,offset_a的值将是0,因为a是结构体的第一个成员,所以它位于结构体的开头。offset_b的值将是4(假设一个int类型占4个字节),因为b位于a之后。
  • 需要注意的是,offsetof宏只能用于结构体和联合体的成员,不能用于数组的元素或者普通的变量。此外,offsetof宏的返回值是size_t类型的,这是一个无符号整数类型,它能够表示任何非负的整数。
  • 总的来说,offsetof宏是一个非常实用的工具,它可以帮助我们方便地获取结构体成员的偏移量,从而在内存中正确地访问和操作这些成员。

🌻3.代码实例

🐓3.1 offsetof宏结构解析

#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE*)0)->MEMBER)
  • TYPE 是结构体的类型;
  • MEMBER 是结构体中的成员名称。
  • 这个宏的作用是计算结构体中某个成员的偏移量,也就是该成员相对于结构体起始地址的偏移量。

宏展开的过程如下:

  • (TYPE*)0:将 0 转换为 TYPE* 类型的指针,这里的目的是获取一个指向类型 TYPE 的空指针。
  • &((TYPE*)0)->MEMBER:获取成员 MEMBER 在结构体 TYPE 中的地址。这里 (TYPE*)0 指向结构体的起始地址,然后使用 -> 运算符访问成员 MEMBER,并取得其地址。
  • ((size_t) &((TYPE*)0)->MEMBER):将成员地址的指针类型转换为 size_t 类型,这是因为偏移量通常是用无符号整数表示的。
    最终结果是结构体成员 MEMBER 相对于结构体起始地址的偏移量,以字节为单位。

🐓3.2 计算结构体成员的偏移量

#include <stdio.h>
#include <stddef.h>struct Example {int x;int y;char z;
};int main() {printf("Offset of x: %zu\n", offsetof(struct Example, x));printf("Offset of y: %zu\n", offsetof(struct Example, y));printf("Offset of z: %zu\n", offsetof(struct Example, z));return 0;
}
  • 使用 offsetof 宏来获取结构体 Example 中各个成员的偏移量。

🐓3.3 通过偏移量访问结构体成员

#include <stdio.h>
#include <stddef.h>struct Example {int x;int y;char z;
};int main() {struct Example obj;int* ptr_y = (int*)((char*)&obj + offsetof(struct Example, y));*ptr_y = 10;printf("obj.y: %d\n", obj.y);return 0;
}
  • 使用偏移量来访问结构体成员 y。
  • 通过将结构体的地址与偏移量相加,我们可以得到成员 y 的地址,并将其视为整型指针,然后通过这个指针修改成员 y 的值。

🐓3.4 在动态分配的结构体数组中使用偏移量

#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>struct Example {int x;int y;char z;
};int main() {int num_objects = 5;struct Example* array = malloc(num_objects * sizeof(struct Example));for (int i = 0; i < num_objects; i++) {int* ptr_x = (int*)((char*)&array[i] + offsetof(struct Example, x));*ptr_x = i;}for (int i = 0; i < num_objects; i++) {printf("array[%d].x = %d\n", i, array[i].x);}free(array);return 0;
}
  • 动态分配的结构体数组中使用偏移量来访问并设置成员 x 的值。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/619192.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

计算机网络——实现smtp和pop3邮件客户端

实验目的 运用各种编程语言实现基于 smtp 协议的 Email 客户端软件。 实验内容 1. 选择合适的编程语言编程实现基于 smtp 协议的 Email 客户端软件。 2. 安装 Email 服务器或选择已有的 Email 服务器&#xff0c;验证自己的 Email 客户端软件是否能进行正常的 Email 收发功…

【web网页制作】html+css旅游家乡山西主题网页制作(3页面)【附源码】

山西旅游网页目录 涉及知识写在前面一、网页主题二、网页效果Page1、景点介绍Page2、酒店精选|出行攻略Page3、景色欣赏 三、网页架构与技术3.1 脑海构思3.2 整体布局3.3 技术说明书 四、网页源码4.1 主页模块源码4.2 源码获取方式 作者寄语 涉及知识 山西旅游主题网页制作&am…

JVM虚拟机(五)强引用、软引用、弱引用、虚引用

目录 一、强引用二、软引用三、弱引用四、虚引用五、总结 引文&#xff1a; 在 Java 中一共存在 4 种引用&#xff1a;强、软、弱、虚。它们主要指的是&#xff0c;在进行垃圾回收的时候&#xff0c;对于不同的引用垃圾回收的情况是不一样的。下面我们就一起来看一下这 4 种引用…

【题目】【信息安全管理与评估】2022年国赛高职组“信息安全管理与评估”赛项样题6

【题目】【信息安全管理与评估】2022年国赛高职组“信息安全管理与评估”赛项样题5 信息安全管理与评估 网络系统管理 网络搭建与应用 云计算 软件测试 移动应用开发 任务书&#xff0c;赛题&#xff0c;解析等资料&#xff0c;知识点培训服务 添加博主wx&#xff1a;liuliu548…

2440栈的实现类型、b系列指令、汇编掉用c、c调用汇编、切换工作模式、初始化异常向量表、中断处理、

我要成为嵌入式高手之4月11日51ARM第六天&#xff01;&#xff01; ———————————————————————————— b指令 标签&#xff1a;表示这条指令的名称&#xff0c;可跳转至标签 b指令&#xff1a;相当于goto&#xff0c;可随意跳转 如&#xff1a;fini…

代理模式(结构型模式)

目录 1、概述 2、结构 2.1、角色分类 2.2、类图 3、静态代理 3.1、案例类图 3.2、案例代码 4、JDK 动态代理 4.1、案例代码 4.2、底层原理 4.3、执行流程说明 5、CGLib 动态代理 5.1、案例代码 6、三种代理的对比 6.1、JDK代理和CGLib代理 6.2、动态代理和静态…

系统架构最佳实践 -- 统一身份认证系统

目录 1.系统架构设计&#xff1a; 2.用户认证与授权&#xff1a; 3.用户身份管理&#xff1a; 4.安全性保障&#xff1a; 5.日志记录与审计&#xff1a; 6.高可用性与容错性&#xff1a; 7.用户体验优化&#xff1a; 随着互联网的快速发展和应用的普及&#xff0c;人们在…

SpringCloud实用篇(四)——Nacos

Nacos nacos官方网站&#xff1a;https://nacos.io/ nacos是阿里巴巴的产品&#xff0c;现在是springcloud的一个组件&#xff0c;相比于eureka的功能更加丰富&#xff0c;在国内备受欢迎 nacos的安装 下载地址&#xff1a;https://github.com/alibaba/nacos/releases/ 启动…

Hadoop 3.1.3

第1章 Hadoop概述 1.1 Hadoop是什么 1.2 Hadoop发展历史&#xff08;了解&#xff09; 1.3 Hadoop三大发行版本&#xff08;了解&#xff09; Hadoop三大发行版本&#xff1a;Apache、Cloudera、Hortonworks。 Apache版本最原始&#xff08;最基础&#xff09;的版本&#x…

IOS 短信拦截插件

在使⽤iOS设备的时候, 我们经常会收到1069、1065开头的垃圾短信, 如果开了iMessage会更严重, 各种乱七⼋糟的垃圾信息会时不时地收到。 从iOS11开始, ⼿机可以⽀持恶短信拦截插件了. 我们可以通过该插件添加⼀些规则通过滤这些不需要的信息. ⼀. 使⽤xcode新建⼀个项⽬ 【1】…

终端工具命令行颜色配置(解决终端工具连上服务器之后,无颜色问题)

本期主题&#xff1a; 讲解使用mobaxterm等终端工具连上服务器&#xff0c;但是命令行没有颜色的问题 目录 1. 问题描述2. 原因解释3.测试 1. 问题描述 使用终端工具&#xff08;Mobaxterm等&#xff09;连上服务器之后&#xff0c;发现终端工具没有颜色&#xff0c;如下图&am…

中国移动传关停8元保号套餐?或是5G成本带来的压力所致

日前有网友发现希望使用中国移动的保号套餐&#xff0c;却发现已无法办理&#xff0c;媒体对此多有报道&#xff0c;这意味着中国移动的套餐业务发生了重大变动&#xff0c;如此做或许在于5G成本上涨带来的压力促使它不得不提高套餐的门槛。 中国移动已建成最多的5G基站&#x…