宏CONTAINING_RECORD,可以直接根据结构体成员指针找到结构体指针。
我们看一下它的定义:
#define CONTAINING_RECORD(addr,type,field) ((type*)((unsigned char*)addr - (unsigned long)&((type*)0)->field))
// addr: 结构体中某个成员变量的地址
// type: 结构体的原型
// field: 结构体的某个成员(与前面相同)
为什么这样就能得到结构体指针?
这个得益于结构体在申请内存空间是一段连续的地址,我们可以通过其中某个成员变量的地址,减去该成员的偏移来得到该成员所在结构体的指针。
那么为何(unsigned long)&((type*)0)->field))能得到某结构体成员的偏移?
这里可以假设某结构体指针地址是0000000,那么该成员的地址就是该成员对于其结构体的偏移
为了论证我们的猜想是对的,你可以无限次数运行以下代码
#include <windows.h>
#include <stdio.h>
struct T{
int a;
int b;
int c;
};
int main()
{
T t = {1,2,3};
printf("结构体指针地址:\t%p\n", &t );
printf("结构体成员a指针地址:\t%p\n", &t.a );
printf("结构体成员b指针地址:\t%p\n", &t.b );
printf("结构体成员c指针地址:\t%p\n", &t.c );
printf("...\n");
printf("下面利用结构体成员c来推算结构体的指针\n");
int *cc = &t.c;
T *tt = CONTAINING_RECORD(cc, T, c);
printf("结构体(T*)0指针地址:\t%p\n", ((T*)0) );
printf("结构体成员c的偏移值:\t%d\n", &((T*)0)->c );
printf("结构体指针地址:\t%p\n", tt );
system("pause");
return 0;
}
运行结果:
分享到:
相关推荐
在C#中,使用MarshalAsAttribute特性来申明结构体成员的类型和长度,例如: [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] public byte[] pData; 在C#中,使用StructLayoutAttribute特性来申明结构体的....
当调用该函数时,所有结构体成员的值会被复制到函数内部的局部变量中。这种方式简单明了,但如果结构体较大,复制操作可能会消耗较多的时间和内存。 2. 结构体指针参数: 另一种方法是通过指针传递结构体。在这种...
本篇文章将深入探讨VC++中结构体的成员变量和方法,以及如何实现结构体成员的调用。 1. **结构体与类的区别** - 默认访问修饰符:在C++中,类的成员默认是私有的(private),而结构体的成员默认是公有的(public...
### 结构体数组与结构体指针 结构体也可以被用来创建数组,或者通过指针处理数组中的元素: ```cpp Student students[3]; // 结构体数组 students[0] = {"赵六", 22, 86.0f}; // ... Student* pStu = students; // ...
在压缩包中,可能会包含使用指针访问结构体成员,动态分配内存,以及通过指针传递参数的示例。 链表是一种动态数据结构,与数组不同,它不必预先分配固定大小的空间。链表由节点组成,每个节点包含数据和指向下一个...
成员运算符(`.`)与指向结构体成员运算符(`->`)是C/C++语言中处理结构体数据类型时非常关键的两个运算符。它们虽然功能相似,但使用场景和语法结构上有着显著的不同。 首先,成员运算符`.`用于访问结构体变量的...
在"JNA 转java接口以及指针结构体解析"这个主题中,我们将深入探讨如何使用JNA来处理C语言中的结构体和指针。 首先,理解JNA的基本工作原理至关重要。JNA通过定义一个`Interface`,该接口中的方法对应于要调用的...
注意,由于跨语言调用,结构体成员的排列顺序、大小和对齐方式必须一致。 接下来,我们需要定义一个C++接口,这个接口包含了一个接受回调函数和结构体参数的函数。在C++中,这可能看起来像这样: ```cpp extern "C...
5. 可能涉及传递结构体指针给函数,展示如何在函数内部操作结构体。 了解了结构体和指针的基本概念后,我们可以利用它们实现各种高级编程技巧,如动态内存分配、数据结构的实现、回调函数等。在实际项目中,熟练...
在C++编程语言中,结构体(struct)是一种自定义数据类型,它允许我们将多个不同类型的变量组合成一个单一的实体。结构体变量的指针是一个非常重要...理解和熟练掌握结构体指针的使用,是提升 C++ 编程技能的关键一步。
C#调用C++ dll, 包括结构体, 数组, 函数指针, 字符串等等
### 结构体对齐、typedef、结构体指针与C++引用详解 #### 一、结构体对齐 **结构体对齐**是指在结构体中的成员变量在内存中的排列方式,这种排列是为了提高CPU访问内存的速度。由于现代处理器的设计倾向于以一定的...
本主题探讨的是如何利用C++的模板机制来实现结构体的序列化配置,以提高代码的可复用性和灵活性。 首先,我们需要理解C++的模板。模板是C++中的一个强大特性,允许我们编写通用的代码,可以应用于多种数据类型。这...
在iOS开发中,C++结构体的使用是一个重要的知识点,特别是在需要跨语言交互或利用C++的高效性能时。本文将深入探讨C++结构体在iOS应用中的解析过程,以及如何在Objective-C或Swift中有效地利用它们。 首先,C++...
通过这个例子,我们可以看到,指针结构体数组和指向结构体变量的指针是C++中处理复杂数据结构的有效工具。它们允许我们高效地操作和管理大量数据,尤其是在需要动态修改和查询数据时。理解这些概念对于深入学习C++...
结构体指针是指向结构体变量的指针,可以通过指针访问结构体成员。 例如: ```cpp struct STRUCT { string hello; }; int main() { STRUCT *str = new STRUCT; str->hello = "Hello"; cout << str->hello ; ...
此外,还定义了一个名为`GetDeviceIdList`的函数,它接收一个`DEVICE_INFO`结构体数组的指针以及一个整型引用`count`作为参数。 #### C#中的结构体定义 接下来,在C#中定义相应的结构体以匹配C++中的定义: ```...
- C++的结构体成员排列可能与C#不同,需要考虑内存对齐问题。 - 在C#中,可能需要使用`[StructLayout(LayoutKind.Sequential)]`来指定布局,以匹配C++的结构体。 3. **函数定义转换**: - C++的函数指针在C#中...
在本示例"C++结构体作为参数Demo"中,我们将探讨如何将结构体作为函数参数来传递,以及这背后的内存管理和性能考虑。 首先,让我们了解结构体的基本概念。结构体允许我们将相关的数据项组合在一起,形成一个复合...
C/C++结构体详解 结构体(struct)是一种自定义的数据类型,它可以包含不同数据类型的成员,具有数组所不具备的一些功能特性。结构体的定义使用 struct 修饰符,例如:struct test { float a; int b; }; 定义了一个...