通过 struct 成员地址 获取 struct 结构体地址
1. 问题描述:
现在定义了一个结构体:
struct Foo
{
int a;
int b;
};
Foo foo;
假如由于函数传参等原因,现在程序只能拿到 foo.b 的地址,这时想通过某种方法获取到 foo 结构体里的其他成员。
那么问题来了,这就是以下主要讨论的内容。
2. 原理概述
将地址 0 强制转换成一个结构体指针,伪代码: struct foo *p = (struct Foo *)0;
从而通过已知的结构体成员的地址减去结构体的首地址得到已知结构体成员的内存偏移 , 伪代码 : offset = &(p->b) - p;
那么问题就简单了, 现在已知 foo.b 的地址,将其减去偏移即可得到该结构体的首地址。
3. 实现举例
//file name : list_head.c
#include <stdio.h> struct list_head
{
struct list_head *next;
}; struct fox
{
unsigned int tail_color;
unsigned int tail_length;
struct list_head list;
}; #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER ) #define container_of(ptr, type, member) ({\
const typeof( ((type *))->member)* __mptr = (ptr);\
(type *)((char*)__mptr - offsetof(type, member));})
int main(int argc, char** argv)
{
unsigned short offset = ;
struct fox *p = ;
struct fox red_fox;
red_fox.tail_color = ;
red_fox.tail_length = ;
unsigned int *p_t; printf("red_fox_addr: %x\n", &red_fox);
printf("tail_color_addr: %x\n", &(red_fox.tail_color));
printf("tail_length_addr: %x\n", &(red_fox.tail_length));
printf("list_addr: %x\n", &(red_fox.list)); // offset = (unsigned char*)&(p->list) - (unsigned char*)p;
offset = offsetof(struct fox, list);
printf("offset: %d \n", offset); p_t = container_of(&red_fox.list, struct fox, list);
printf("red_fox_addr: %x\n", p_t);
printf("tail_color: %d \n", ((struct fox *)p_t)->tail_color);
printf("tail_length: %d \n", ((struct fox *)p_t)->tail_length); return ;
}
4. 应用
Linux 中数据结构单链表使用的这种方法。好处也是显而易见的,当用户想通过单链表实现自己封装的数据结构时不需要在单独结构体定义单链表遍历的指针和相关函数,仅仅实现包含 list_head 这个结构体成员即可。而内核提供了完整且高效的用于单链表操作 api.
作者能力有限,如发现错误欢迎指正。
通过 struct 成员地址 获取 struct 结构体地址的更多相关文章
- list_entry(ptr, type, member)——知道结构体内某一成员变量地址,求结构体地址
#define list_entry(ptr, type, member) \ ((type *)(() -> member))) 解释: 1 在0这个地址看做有一个虚拟的type类型的变量,那 ...
- Linux中的两个经典宏定义:获取结构体成员地址,根据成员地址获得结构体地址;Linux中双向链表的经典实现。
倘若你查看过Linux Kernel的源码,那么你对 offsetof 和 container_of 这两个宏应该不陌生.这两个宏最初是极客写出的,后来在Linux内核中被推广使用. 1. offse ...
- 由结构体成员地址计算结构体地址——list_entry()原理详解
#define list_entry(ptr, type, member) container_of(ptr, type, member) 在进行编程的时候,我们经常在知道结构体地址的情况下,寻找其中 ...
- typedef struct xxx xxx与struct xxx区别 && “->”和“.”访问结构体变量
1. struct //是C中的结构体的关键词.如: stuct node{ int a;.....} a; node 相当于结构体的类型,关键是其实在C中stuct node 才相当于一个数据类型, ...
- nginx取结构体地址
linux内核提供了一个container_of()宏,可以根据结构体某个成员的地址找到父结构的地址. #define container_of(ptr, type, member) ({ \ con ...
- 获取客户机MAC地址 根据IP地址 获取机器的MAC地址 / 获取真实Ip地址
[DllImport("Iphlpapi.dll")] private static extern int SendARP(Int32 dest, Int32 host, ref ...
- struct的成员对齐问题-结构体实际大小问题
struct的成员对齐 注意:为了方便说明,等号左边是每个数据单独所占长度,右边是最终空间大小,以字节为单位. 一.什么时间存在对其问题:(32位机对齐方式是按照4字节对其的,以下所有试验都是在32位 ...
- C语言根据结构体成员变量的地址,得到结构体的地址
看nginx代码时发现双链表使用的是这种方法,记录一下 给出一个实例来说明 struct father_t { int a; char *b; double c;}f;char *p ...
- golang中内存地址计算-根据内存地址获取下一个内存地址对应的值
package main import ( "fmt" "unsafe" ) func main() { // 根据内存地址获取下一个字节内存地址对应的值 da ...
随机推荐
- Advanced Installer
Advanced Installer是一款功能强大.可生成符合 MS Windows 认证的 Windows Installer 的 MSI 安装包制作工具,具有友好的图形用户界面,直观而且非常简单的 ...
- request 和response 中的setCharacterEncoding区别
response和request的setCharacterEncoding 一.request.setCharacterEncoding():是设置从request中取得的值或从数据库中取出的值. 指 ...
- [转]HTML accesskey 属性
本文转自:http://www.dreamdu.com/xhtml/attribute_accesskey/ 17.2. HTML accesskey 属性 accesskey 属性 -- 代表链 ...
- CF Polycarpus' Dice (数学)
Polycarpus' Dice time limit per test 1 second memory limit per test 256 megabytes input standard inp ...
- hdu 1423 最长公共递增子序列
这题一开始把我给坑了,我还没知道LCIS的算法,然后就慢慢搞吧,幸运的是还真写出来了,只不过麻烦了一点. 我是将该题转换为多条线段相交,然后找出最多多少条不相交,并且其数值死递增的. 代码如下: #i ...
- 多tab页框架的使用场合
多tab页框架适合应用于功能较少的场合,例如邮箱后台之类的. 对于一些业务功能多且复杂的场合就不适用.打开过多的tab页容易给用户造成混乱,页面的跳转也存在一定的难度. 一种新技术不能完全取代旧技术, ...
- ubuntu忘记密码,忘记root密码的解决方法
转载于http://forum.ubuntu.org.cn/viewtopic.php?t=272164 ubuntu的root默认是禁止使用的,在安装的时候也没要求你设置root的密码,和红帽系统系 ...
- python学习day4--python基础--元组,字符串
1.元组 #只读列表,元组,当希望生成后不被修改则用元组 r=(1,2,3,4,5) 元组 2.字符串,python字符串操作非常丰富,编程时可先查询python本身是否已设计了相关函数 #移除空白 ...
- JAVA 基础加强学习笔记
一.面向对象 (一)继承 1.继承的好处: (1) 提高了代码的复用性. (2) 让类与类之间产生了关系,提供了另一个特征多态的前提. 注意: 子类中所有的构造函数都会默认访问父类中的空参数的构造函 ...
- JAVA输入/输出系统中的其他流学习笔记
一.字节数组流 字节数组流类能够操作内存中的字节数组,它的数据是一个字节数组.字节数组流类本身适配器设计模式,它把字节数组类型转为流类型使得程序能够对字节数组进行读写操作. 1.ByteArrayIn ...