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

news2024/12/23 18:52:45

简介: 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.coloradmin.cn/o/1611553.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Redis】Hash数据类型

文章目录 常用命令hset & hgethexists & hdelhkeys & hvals & hgetallhlen & hmgethsetnxhincrby & hincrbyfloat 内部编码 Hash 相比于 string 而言可以节省很多个 key &#xff0c;一个 key 里面又可以包含了多个 key-value 常用命令 hset & hg…

密码学 | 承诺:绑定性 + 隐藏性

&#x1f951;原文&#xff1a;承诺方案&#xff08;Commitment&#xff09;学习笔记 &#x1f951;写在前面&#xff1a; 本文属搬运博客&#xff0c;自己留存学习。本文只会讲承诺的两个安全属性&#xff0c;不会再讲解承诺的定义。 正文 承诺方案需要满足两个安全属性&…

云手机助力舆情监测,智慧引领信息时代

随着信息时代的到来&#xff0c;舆情监测已成为政府、企业、高校、金融机构等各行业的必备利器。在这个信息爆炸的时代&#xff0c;如何及时准确地感知民意、把握市场动态&#xff0c;已成为各界迫切需要解决的问题。而云手机作为信息时代的新生力量&#xff0c;在舆情监测方面…

「GO基础」变量

&#x1f49d;&#x1f49d;&#x1f49d;欢迎莅临我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:「stormsha的主页」…

上位机图像处理和嵌入式模块部署(树莓派4b和视觉slam十四讲)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 实际使用中&#xff0c;树莓派4b是非常好的一个基础平台。本身板子价格也不是很贵&#xff0c;建议大家多多使用。之前关于vslam&#xff0c;也就是…

《强势》如何在工作、恋爱和人际交往中快速取得主导权? - 三余书屋 3ysw.net

强势&#xff1a;如何在工作、恋爱和人际交往中快速取得主导权&#xff1f; 大家好&#xff0c;今天我们要解读的是一本名为《强势》的书籍。我将花费大约20分钟的时间&#xff0c;为您详细讲解这本书的精华内容&#xff0c;包括如何在家庭关系、职场关系和朋友关系中迅速取得…

Python可视化数据分析-柱状图/折线图

一、前言 使用python编写一个图表生成器&#xff0c;输入各公司的不良品数量&#xff0c;可以在一张图中同时展示数据的柱状图和折线图。 效果如下&#xff1a; 二、基础知识 绘制折线图和柱状图主要使用到了 pyecharts.charts 模块中的 Line 和 Bar 类。它们允许用户通过简…

Java关键字和API

1 this和super关键字 1.this和super的意义 this&#xff1a;当前对象 在构造器和非静态代码块中&#xff0c;表示正在new的对象 在实例方法中&#xff0c;表示调用当前方法的对象 super&#xff1a;引用父类声明的成员 无论是this和super都是和对象有关的。 2.this和sup…

python-自动化篇-终极工具-用GUI自动控制键盘和鼠标-pyautogui-键盘

文章目录 键盘键盘——记忆宫殿入门——通过键盘发送一个字符串——typewrite()常规——键名——typewrite()常规——按下键盘——keyDown()常规——释放键盘——keyUp()升级——热键组合——hotkey() 键盘 pyautogui也有一些函数向计算机发送虚拟按键&#xff0c;让你能够填充…

嵌入式物联网实战开发笔记-乐鑫ESP32芯片功能对比以及功能选型【doc.yotill.com】

乐鑫ESP32入门到精通项目开发参考百例下载&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1ATvRnAZvxkev-PJfd3EAPg?pwd4e33 提取码&#xff1a;4e33 2.1 初识 ESP32 ESP32-S3 是一款低功耗的 MCU 系统级芯片 (SoC)&#xff0c;支持 2.4 GHz Wi-Fi 和低功耗蓝牙 (…

【PythonCode】力扣Leetcode16~20题Python版

【PythonCode】力扣Leetcode16~20题Python版 前言 力扣Leetcode是一个集学习、刷题、竞赛等功能于一体的编程学习平台&#xff0c;很多计算机相关专业的学生、编程自学者、IT从业者在上面学习和刷题。 在Leetcode上刷题&#xff0c;可以选择各种主流的编程语言&#xff0c;如C…

汇编语言(详解)

汇编语言安装指南 第一步&#xff1a;在github上下载汇编语言的安装包 网址&#xff1a;GitHub - HaiPenglai/bilibili_assembly: B站-汇编语言-pdf、代码、环境等资料B站-汇编语言-pdf、代码、环境等资料. Contribute to HaiPenglai/bilibili_assembly development by creat…

一文让你彻底掌握操作符(超详细教程)

✅作者简介&#xff1a;大家好&#xff0c;我是小杨 &#x1f4c3;个人主页&#xff1a;「小杨」的csdn博客 &#x1f525;系列专栏&#xff1a;小杨带你玩转C语言【初阶】 &#x1f433;希望大家多多支持&#x1f970;一起进步呀&#xff01; 大家好呀&#xff01;我是小杨。小…

学习笔记-数据结构-线性表(2024-04-18)- 单向链表选择排序

试以单向链表为存储结构实现简单选择排序的算法。 实现递增排序&#xff0c;首先选择一个元素作为第一个比较值&#xff0c;遍历其他所有的元素&#xff0c;如果发现其他元素中有比它小的元素&#xff0c;则交换两个元素&#xff0c;这样每一趟都能找到符合要求的最小值 正经…

Turnitin查重时,论文里面的图片会不会被查到?

在撰写论文的时候&#xff0c;论文里面插入几张图片作为观点和数据的阐述在再正常不过了。但是&#xff0c;一旦涉及到论文查重&#xff0c;事情就变得有点复杂了。许多同学早使用Turnitin检测系统&#xff08;www.checktoo.com&#xff09;对论文查重时&#xff0c;就常问题到…

记录交叉编译环境配置--海思开发板的 嵌入式nginx和 php的移植

嵌入式 lnmp搭建的记录 一些交叉编译的配置环境思路分享&#xff1a;P&#xff1a;php编译PHP可能遇到的问题configure阶段&#xff1a;Makefile-make阶段&#xff1a;Makefile-make install阶段&#xff1a; N&#xff1a;Nginx 文章比较水&#xff0c;并没有没解决什么实际问…

现货白银保证金交易要先分析趋势

现货白银是保证金交易品种&#xff0c;买卖过程中可能会涉及数十倍的资金杠杆&#xff0c;所以它对投资者的分析水平和交易水平的要求都比较高&#xff0c;所以在进入这个市场之前&#xff0c;投资者需要先学习一些基本的分析方法&#xff0c;当中可以分为基本面和技术面两大流…

2024年外贸独立站建设首选:WordPress引领市场,助力企业出海

随着全球经济的不断融合与发展&#xff0c;越来越多的企业开始关注海外市场&#xff0c;希望通过建设外贸独立站来扩大品牌影响力和销售额。在众多的内容管理系统&#xff08;CMS&#xff09;中&#xff0c;WordPress以其强大的功能、丰富的插件资源和用户友好的操作界面&#…

医学临床预测模型发展新趋势-并联式

医学临床预测模型发展新姿势-并联式 现有的预测模型是对单个结局指标进行分类或者回归&#xff0c;得出最终的结论&#xff0c;而辅助医生进行临床决策。众所周知&#xff0c;临床决策过程中&#xff0c;医生通常会考虑多个结局指标来做出最终的决策&#xff1b;临床研究中也通…

多因子模型的因子分组-克隆巴赫α系数

优质博文&#xff1a;IT-BLOG-CN 在建立我们的Alpha模型之前&#xff0c;我们得先知道什么是Alpha&#xff1f;Alpha是一条或者一系列能够预测股票走势的信息资讯组合。而这每一条非随机的信息资讯&#xff0c;我们称之为多因子模型的因子。多因子模型因子的选择需要避免系统性…