• 通过结构体某个成员的地址计算结构体首地址 (转)


    最近在CU论坛上有很多人在问这样一个问题:给出一个结构体成员的地址计算该结构体的起始地址。其实这个题我之前也没有接触过,据说内核代码中有这样用的,但还没有看到。不过觉得这个题的解决方法还是有一定技巧的,就总结一下。下面是实现的代码。

     1 #include <stdio.h>
     2 #include <stdlib.h>
     3 #define STRUCT_OFFSET(stru_name, element) (unsigned long)&((struct stru_name*)0)->element
     4 struct stru_addr 
     5 {
     6     int a;
     7     char b;
     8     int d;
     9     char c;
    10 
    11 };
    12 
    13 int main()
    14 {
    15     struct stru_addr s;
    16     unsigned long offset = 0;
    17     printf("start addr of s = %x
    ", &s.a);
    18     
    19     offset = STRUCT_OFFSET(stru_addr, c);
    20 
    21     printf("c_addr = %x, offset = %u
    ", &s.c, offset);
    22     printf("start addr of s caculated from c addr: %x
    ", (char *)&s.c - offset);
    23     system("pause");
    24     return 0;
    25 }

    其实整个程序中最关键的部分就是如何求出结构体中某个成员相对于结构体首地址的偏移量。这里的解决方法是:假设存在一个虚拟地址0,将该地址强制转换成为该结构体指针类型(struct stru_name*)0。那么地址0开始到sizeof(struct)-1长度的内存区域就可以视为一个结构体的内存。这样结构体中任何一个元素都可以通过对该结构体指针解引用得到。由于该结构体的起始地址为0, 因此任何一个成员的地址应该等于其相对于结构体起始地址的偏移,这也就是计算偏移量的方法:(unsigned long)&((struct stru_name*)0)->element。

    上面程序执行的结果如下:

    1 [root@localhost tmp]# ./a.out 
    2 start addr of s = bf81b820
    3 c_addr = bf81b82c, offset = 12
    4 start addr of s caculated from c addr: bf81b820

    上述的结果中还同时考虑了结构体内的对齐问题。

    原文地址:http://blog.chinaunix.net/uid-10167808-id-25940.html

  • 相关阅读:
    关于MQ的对比
    关于RabbitMQ(二)
    关于QPS、TPS、并发用户数、吞吐量的关系
    关于使用Ecplise构建gradle项目
    关于记录一次线上真实环境多线程引发的问题
    关于MySQL——find_in_set()函数的使用
    关于数据库的表连接
    关于Java线程池
    IntelliJ搭建Scala及Spark工程
    idea编写wordcount程序及spark-submit运行
  • 原文地址:https://www.cnblogs.com/challenge1230/p/4383012.html
Copyright © 2020-2023  润新知