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

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

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

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

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

欢迎关注Android系统攻城狮

🌻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 的值。

相关推荐

  1. 每天一个数据分析题(

    2024-04-15 07:02:02       46 阅读
  2. C语言经典面试题目(

    2024-04-15 07:02:02       35 阅读
  3. SQL世界函数+语句

    2024-04-15 07:02:02       44 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-04-15 07:02:02       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-04-15 07:02:02       100 阅读
  3. 在Django里面运行非项目文件

    2024-04-15 07:02:02       82 阅读
  4. Python语言-面向对象

    2024-04-15 07:02:02       91 阅读

热门阅读

  1. typora支持的流程图的语法

    2024-04-15 07:02:02       41 阅读
  2. CSS函数大观:新手入门全面指南

    2024-04-15 07:02:02       34 阅读
  3. 正确处理Go语言中的瞬时资源

    2024-04-15 07:02:02       38 阅读
  4. 课时95:脚本自动化_脚本信号_信号捕捉

    2024-04-15 07:02:02       36 阅读
  5. 嵌AR/VR开发教程和案例

    2024-04-15 07:02:02       29 阅读
  6. [MAC] mac电脑更新 git的安装homebrew

    2024-04-15 07:02:02       38 阅读
  7. zustand状态库在react类组件中使用

    2024-04-15 07:02:02       36 阅读