必威体育Betway必威体育官网
当前位置:首页 > IT技术

offsetof 和 container_of 的用途

时间:2019-10-31 09:44:29来源:IT技术作者:seo实验室小编阅读:89次「手机版」
 

offsetof

offsetof() 和 container_of() 两个宏定义在linux内核中很常见。我们在应用程序编程时可能也需要用到,因此可以把这两个宏定义copy过来。

offsetof(type, member)用来求结构体type中的member成员在type中的偏移, 其定义如下:

#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)

例如对于结构体:

struct test_s {
    int a;
    int b;
    int c;
};

那么 offsetof(struct test_s, c) 就等于8。

container_of(ptr, type, member)宏用来通过结构体的某个成员的指针来获得指向整个结构体的指针。

/**
 * container_of - cast a member of a structure out to the containing structure
 * @ptr:    the pointer to the member.
 * @type:   the type of the container struct this is embedded in.
 * @member: the name of the member within the struct.
 *
 */
#define container_of(ptr, type, member) ({          \
    const typeof( ((type *)0)->member ) *__mptr = (ptr);    \
    (type *)( (char *)__mptr - offsetof(type,member) );})

其中,type是结构体的类型,member是结构体中这个成员的名字,ptr是指向这个成员的实例的指针。例如对于结构体:

struct cAMDev {
    int a;
    int c;
    int b;
};

那么下面代码的结果就是将指针zzp指向了结构体zz。

struct camdev zz; //一个结构体实例
struct camdev * zzp;
zzp = container_of(&(zz.c), struct camdev, c);

当然这个代码只是举例用的,实际场景可能是,我们不知道zz在哪定义及其地址,但知道c是这个结构体的成员且知道c的指针,这时就可以用container_of获取zz的实例。

-

需要说明两点:

1. offsetof()宏展开后的内容是在编译阶段(编译过程的第二阶段)被处理掉的,而不是运行时,所以用0地址来取成员不会出现异常。

2. container_of()和offsetof()是内核中提供的宏,我们写应用程序时不能直接用,而是要重新定义。

随便再说一点:可计算的成员偏移都可以在编译阶段得出结果,例如我看到一个程序如下:

#include <stdio.h>

struct str{
    int len;
    char s[0];
};

struct foo {
    struct str *a;
};

int main(int argc, char** argv) {
    struct foo f={0};
    if (f.a->s) {
        printf("%x\n", f.a->s);
    }
    return 0;
}

这个程序执行时并不会报错,打印结果为4。因为虽然 f = {0} 是将a指向了NULL,但代码中printf是在打印 f.a->s 的地址,这在编译期间就可以算出来。如果把%x改为%s程序就崩溃了,因为你试图访问s指向的内容。

文章最后发布于: 2018-03-22 15:26:48

相关阅读

关于offsetof(s,m)的解析

关于offsetof(s,m)的解析在一些库的写法中,我们有时会看到如下的宏定义:#define OFFSETOF(s,m) ((INT32U)&(((s *)0->m))其作用其实是

Linux下offsetof与container_of结构体

转载:http://www.cnblogs.com/skywang12345/p/3562146.html Linux中的两个经典宏定义 倘若你查看过Linux Kernel的源码,那么你对

C语言高级用法---container_of()

在Linux内核源码中,实现和链表相关的接口list_entry()时,会调用container_of()宏定义,它的作用是:给定结构体中某个成员的地址、该结

C/C++ offsetof

offsetofRetrieves the offset of a member from the beginning of its parent structure.返回结构成员相对于结构开头的字节偏移

container of()函数简介

在linux 内核编程中,会经常见到一个宏函数container_of(ptr,type,member), 但是当你通过追踪源码时,像我们这样的一般人就会绝望了(

分享到:

栏目导航

推荐阅读

热门阅读