zoukankan      html  css  js  c++  java
  • C++ offsetof

    这是一个宏,用于计算类中某个成员的地址相对于类实例的偏移量

    在C++11中,要求这个类standard_layout

    基本用法是这样子的:

    #include <stdio.h>      /* printf */
    #include <stddef.h>     /* offsetof */
    
    struct foo {
        char a;
        char b[10];
        char c;
    };
    
    int main ()
    {
        printf ("offsetof(struct foo,a) is %d
    ",(int)offsetof(struct foo,a));
        printf ("offsetof(struct foo,b) is %d
    ",(int)offsetof(struct foo,b));
        printf ("offsetof(struct foo,c) is %d
    ",(int)offsetof(struct foo,c));
    
        printf("%d
    ", &(((struct foo*)0)->c));
        
        return 0;
    }

    注意除了用offsetof宏之外, printf("%d ", &(((struct foo*)0)->c));也是一种办法

    求取某个特定成员的偏移量的意义在哪儿呢?

    linux内核中对于这一特性有一个绝佳的应用。内核数据结构中用到了很多的双向链表,进程描述符、页面描述符等等,它们各自被定义成不同

    的结构体类型,但就双向链表这一数据结构而言,操作却是完全一致的,听起来该是c++模板大显身手的地方了。

    于是就想到定义这样一种链表节点:

    struct list_head
    {
        struct list_head *next, *prev;
    };

    需要使用双向链表的类型就会含有这样的成员,比如:

    typedef struct page
    {
        struct list_head list;
        .....
        struct page *next_hash;
       .....
        struct list_head lru;
    }mem_map_t;

    这里面的成员(list或者lru)都会与其它page结构体中对应的链表节点成员相连,相当于成为一个连接件。

    问题是我们要的是两个page结构之间相连,你弄成它们的成员相连,怎么用呢??

    这就是offsetof大显身手的时候了,有了它,我们在知道成员地址之后,能求出page实例的基地址,从而

    变相的实现了将两个page连接在一起的目的,同时复用了双链表这一基本数据结构。

  • 相关阅读:
    LINQ中selectManay操作符(五)
    LINQ中select操作符(四)
    高效并发进阶-白银
    JVM回收算法
    一个类是怎么被JVM执行的
    一纸理解JVM
    单例模式
    深入理解Spring AOP思想
    深入理解Spring IOC工作原理
    HashMap扩容全过程
  • 原文地址:https://www.cnblogs.com/hustxujinkang/p/5034204.html
Copyright © 2011-2022 走看看