zoukankan      html  css  js  c++  java
  • 计算结构体首地址的技巧

    struct ABC
    {
        int a;
        int b;
        int c;
    };
    
    +----------+   <------我们需要计算的是这个地址。
    | a(4Byte) |
    +----------+   <------这个地址是已知的。
    | b(4Byte) |
    +----------+
    | c(4Byte) |
    +----------+
    通过上图可看出,只需要把当前知道的成员变量的地址ptr,减去它在结构体当中相对偏移量(4),就得到了结构体的首地址(ptr-4).
    设计一个type类型的结构体,起始地址为0,编译器将结构体的起始的地址加上此结构体成员变量的偏移得到此结构体成员变量的偏移地址,
    由于设计的结构体起始地址为0,所以此结构体成员变量的偏移地址就等于其成员变量在结构体内的距离结构体开始部分的偏移量。 Linux内核中,用两个非常巧妙地宏实现了,一个是offsetof宏,另一个是container_of宏:
    1.offsetof宏(获得一个结构体变量成员在此结构体中的偏移量) #define offsetof(struct_type, member_name) ((size_t) & ((struct_type *)0)->member_name ) 【分析】: (1) 该宏中,struct_type为结构体类型,member_name为结构体内的变量名 (2) ((struct_type *)0) 是欺骗编译器说有一个指向结构struct_type 的指针,其地址值0 (3) &((struct_type *)0)->member_name 是要取得结构体struct_type中成员变量member_name的地址. (4) 最后将其值强转为size_t,即转化为一个常数值,而不是将其当作地址进行使用。 因为基址为0,所以,这时member_name的地址当然就是member_name在struct_type中的偏移了。 2. container_of宏(从结构体[struct_type]某成员变量[member_name]指针[member_addr]来求出该结构体[struct_type]的首指针) #define container_of(member_addr, struct_type, member_name) ({const typeof( ((struct_type *)0)->member_name ) *__mptr = (member_addr); (struct_type *)( (char *)__mptr - offsetof(struct_type,member_name) );})
    或者直接定义
    #define container_of(member_addr, struct_type, member_name)   ((struct_type *)( (char *)member_addr - offsetof(struct_type,member_name) )) 【分析】: (
    1)typeof( ( (struct_type *)0)->member )为取出member_name成员的变量类型。 (2) 定义__mptr指针member_addr为指向该成员变量的指针(即指向member_addr所指向的变量处) (3) (char *)__mptr - offsetof(struct_type,member_name)) 用该成员变量的实际地址减去该变量在结构体中的偏移,来求出结构体起始地址。 (4) ({ })这个扩展返回程序块中最后一个表达式的值。
  • 相关阅读:
    python学习之- 内置函数
    python学习之- 生成器/迭代器
    python学习之-- 装饰器
    python基础之
    Python基础之 一 字符编码及转换
    为什么utf8占用3个字节
    Python基础之 一 文件操作
    IIS6与IIS7中如何设置文件过期
    分布式缓存系统Memcached简介与实践
    Log4net
  • 原文地址:https://www.cnblogs.com/eric-geoffrey/p/3811630.html
Copyright © 2011-2022 走看看