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 结构体地址的更多相关文章

  1. list_entry(ptr, type, member)——知道结构体内某一成员变量地址,求结构体地址

    #define list_entry(ptr, type, member) \ ((type *)(() -> member))) 解释: 1 在0这个地址看做有一个虚拟的type类型的变量,那 ...

  2. Linux中的两个经典宏定义:获取结构体成员地址,根据成员地址获得结构体地址;Linux中双向链表的经典实现。

    倘若你查看过Linux Kernel的源码,那么你对 offsetof 和 container_of 这两个宏应该不陌生.这两个宏最初是极客写出的,后来在Linux内核中被推广使用. 1. offse ...

  3. 由结构体成员地址计算结构体地址——list_entry()原理详解

    #define list_entry(ptr, type, member) container_of(ptr, type, member) 在进行编程的时候,我们经常在知道结构体地址的情况下,寻找其中 ...

  4. typedef struct xxx xxx与struct xxx区别 && “->”和“.”访问结构体变量

    1. struct //是C中的结构体的关键词.如: stuct node{ int a;.....} a; node 相当于结构体的类型,关键是其实在C中stuct node 才相当于一个数据类型, ...

  5. nginx取结构体地址

    linux内核提供了一个container_of()宏,可以根据结构体某个成员的地址找到父结构的地址. #define container_of(ptr, type, member) ({ \ con ...

  6. 获取客户机MAC地址 根据IP地址 获取机器的MAC地址 / 获取真实Ip地址

    [DllImport("Iphlpapi.dll")] private static extern int SendARP(Int32 dest, Int32 host, ref ...

  7. struct的成员对齐问题-结构体实际大小问题

    struct的成员对齐 注意:为了方便说明,等号左边是每个数据单独所占长度,右边是最终空间大小,以字节为单位. 一.什么时间存在对其问题:(32位机对齐方式是按照4字节对其的,以下所有试验都是在32位 ...

  8. C语言根据结构体成员变量的地址,得到结构体的地址

    看nginx代码时发现双链表使用的是这种方法,记录一下 给出一个实例来说明 struct father_t {    int a;    char *b;    double c;}f;char *p ...

  9. golang中内存地址计算-根据内存地址获取下一个内存地址对应的值

    package main import ( "fmt" "unsafe" ) func main() { // 根据内存地址获取下一个字节内存地址对应的值 da ...

随机推荐

  1. 前端必会的js知识总结整理

    1.晨曦. 2.js是一门什么样的语言及特点?         js是一种基于对象和事件驱动的并具有相对安全性的客户端脚本语言.也是一种广泛用于web客户端开发的脚本语言,常用来给html网页添加动态 ...

  2. 修改eclipse中web项目的server部署路径

    和MyEclipse不一样,在Eclipse中做的Web项目默认是不支持将项目发布到Web服务器上的,会发布到工作空间的某个目录,因此无法在外部启动Tomcat来运行Web项目,只有打开Eclipse ...

  3. 今天用css做了一个QQ登录页面

    <!doctype html> <html> <head> <meta charset="utf-8"> <title> ...

  4. Android中用PULL解析XML

    解析XML的方式有DOM,SAX,PULL,那为什么要在Android中使用PULL解析呢?首先来说一下PULL解析的优点,然后再说一下其他两种解析方式的缺点,答案就清晰可见啦. DOM不适合文档较大 ...

  5. 在Ubuntu中USB连接手机调试

    1.打开手机USB调试功能 显示“开发者选项”(开发者选项默认隐藏,一般需要进入到“设置”-->“关于手机”连续点击七次,可将“开发者选项显示出来”) 将“开发者选项”设置为“开启”状态 打开U ...

  6. IIS实现301重定向

    301永久重定向对SEO无任何不好的影响,而且网页A的关键词排名和PR级别都会传达给网页B,网站更换了域名,表示本网页永久性转移到另一个地址,对于搜索引擎优化|SEO来说,给搜索引擎一个友好的信息,告 ...

  7. (转)SQL按照日、周、月、年统计数据

    写sql语句分别按日,星期,月,季度,年统计销售额 --按日 select sum(consume),day([date]) from consume_record where year([date] ...

  8. 【译】 Node.js v0.12的新特性 -- Cluster模式采用Round-Robin负载均衡

    原文:https://strongloop.com/strongblog/whats-new-in-node-js-v0-12-cluster-round-robin-load-balancing 本 ...

  9. css 笔记——设置禁用中文输入法

    ime-mode ime-mode的语法解释如下: ime-mode : auto | active | inactive | disabled 取值: auto  : 默认值.不影响IME的状态.与 ...

  10. (POJ 3694) Network 求桥个数

    题目链接:http://poj.org/problem?id=3694Description A network administrator manages a large network. The ...