offsetof宏的使用、模拟实现及 (size_t)&(((struct_type*)0)->mem_name)的解释

宏原型:offsetof(type,member)

作用: 返回数据结构或联合体类型中成员的偏移量,以字节为单位

返回值: size_t类型的无符号整数

使用案例:

cpp 复制代码
#include <stdio.h>    
#include <stddef.h>   

struct foo {
	char a;
	char b[10];
	char c;
};

int main()
{
	printf("offsetof(struct foo,a) is %d\n", (int)offsetof(struct foo, a));
	printf("offsetof(struct foo,b) is %d\n", (int)offsetof(struct foo, b));
	printf("offsetof(struct foo,c) is %d\n", (int)offsetof(struct foo, c));
	return 0;
}

模拟实现:

cpp 复制代码
#include <stdio.h>
//写一个宏,计算结构体中某变量相对于首地址的偏移,并给出说明
struct Stu
{
	int a;
	char c;
	double d;
};

#define OFFSETOF(struct_type, mem_name)      (size_t)&(((struct_type*)0)->mem_name)
//这样的强制类型转换应该使用 (size_t) 而不是 (int) 
//为了确保能够存储较大范围内的偏移值

int main()
{
	printf("%d\n", OFFSETOF(struct Stu, a));
	printf("%d\n", OFFSETOF(struct Stu, c));
	printf("%d\n", OFFSETOF(struct Stu, d));
	return 0;
}

关于"(size_t)&(((struct_type*)0)->mem_name)"的解释:

该表达式的作用是用于获取结构体成员相对于结构体在内存中的偏移量,它将 0 强制类型转换为指向 struct_type 类型的空指针,获取结构体中成员的地址后再强制转换为无符号整型size_t。

注意事项:

  1. 这种技巧通常用于底层编程或者涉及到直接操作内存布局和字节对齐等细节时。一般情况下,在正常应用程序开发过程中不建议频繁使用此类技巧。
  2. 在实际应用时,请确保遵循相关语言和平台规范,并小心处理可能出现未定义行为或错误结果的情况。
    关于"(struct_type*)0"的解释:

在 C 和 C++ 中,整数 0 可以被隐式地转换为空指针。

注意事项:在实际应用中,并不推荐将整数 0 直接强制转换为空指针。根据 C 和 C++ 的规范,在大多数情况下,应该使用 NULL 或 nullptr 来表示空指针。

关于将地址强制类型转换为size_t类型后如何获取偏移量的解释:

cpp 复制代码
#include <stdio.h>
typedef struct {
    int member1;
    char member2;
    double member3;
} MyStruct;

int main() {
    MyStruct myStruct;
    // 获取成员变量的地址
    int* ptr_member1 = &myStruct.member1;
    char* ptr_member2 = &myStruct.member2;

    size_t member1 = ptr_member1;
    size_t member2 = ptr_member2;
    size_t all = &myStruct;

    printf("%u\n", all);
    printf("%u\n", member1);
    printf("%u\n", member2);

    return 0;
}

在这里我们获取了结构体本身地址强制类型转换为size_t后的值2845767320,以及它的两个成员强转后的值2845767320和2845767324,我们可以发现貌似只需要对这些值进行简单的减法运算就可以得到结构体每个成员相对于结构体在内存上的偏移量,但是我们发现关于**#OFFSETOF自定义宏** 包括主函数中并未提及减法操作,但还是得到了相应的偏移量,这是因为:**编译器在处理空指针时会有隐式行为:****在获取结构体成员地址时,默认情况下编译器会计算出从起始位置(即空指针)到该成员之间的偏移量。**然后就该偏移量被强制类型转换为size_t型输出......

~over~

相关推荐
JSMSEMI1117 小时前
JSM12N60C 600V N沟道增强型功率MOSFET
开发语言·javascript·ecmascript
设计师小聂!17 小时前
Java异常处理
java·开发语言·后端·编辑器·idea
清水白石00817 小时前
从打印对象到高质量调试:彻底理解 Python 中 `__repr__` 和 `__str__` 的区别
开发语言·python
枕星而眠17 小时前
C++ 面向对象核心机制深度解析:多态性、虚函数、虚继承与 final 类
运维·开发语言·c++·后端
小蒋学算法17 小时前
算法-乘法表中第K小的数-二分
数据结构·算法
Evand J17 小时前
【MATLAB例程】自适应渐消扩展卡尔曼滤波(AFEKF)三维雷达目标跟踪|效果已调优,附下载链接和运行结果,代码直接运行即可
开发语言·算法·matlab·目标跟踪·卡尔曼滤波·自适应滤波·代码定制
爱装代码的小瓶子17 小时前
3. 设计buffer模块
linux·服务器·开发语言·c++·php
郝学胜-神的一滴17 小时前
Qt 高级开发 027: QTabWidget自定义样式表美化实战
开发语言·c++·qt·程序人生·软件构建·用户界面
keykey6.17 小时前
迁移学习实战:用预训练模型做图像分类
开发语言·人工智能·深度学习·机器学习
双河子思17 小时前
《代码整洁之道》——读书笔记(持续更新)
开发语言·c++·c#