1、老生常谈的两个宏(Linux)
Linux内核中常用的两个宏定义
见招拆招-第—式:谝译器做了什么?
offsetof用于计算TYPE结构体中MEMBER成员的偏移位置
2、编程实验
扫描二维码关注公众号,回复:
890009 查看本文章
offsetof原理剖析 offsetof.c
- #include <stdio.h>
- #ifndef offsetof
- #define offsetof(TYPE, MEMBER) ((size_t)&((TYPE*)0)->MEMBER) //根本不会访问0地址处,只是做加法
- #endif
- struct ST
- {
- int i; // 0
- int j; // 4
- char c; // 8
- };
- void func(struct ST* pst)
- {
- int* pi = &(pst->i); // 0
- int* pj = &(pst->j); // 4
- char* pc = &(pst->c); // 8
- printf("pst = %p\n", pst);
- printf("pi = %p\n", pi);
- printf("pj = %p\n", pj);
- printf("pc = %p\n", pc);
- }
- int main()
- {
- struct ST s = {0};
- func(&s);
- func(NULL);
- printf("offset i: %d\n", offsetof(struct ST, i));
- printf("offset j: %d\n", offsetof(struct ST, j));
- printf("offset c: %d\n", offsetof(struct ST, c));
- return 0;
- }
见招拆招-第二式:
( { } ) 是何方神圣?
- ( { } )是GNU C编译器的语法扩展
- ( { } ) 与逗号表达式类似, 结果为最后—个语句的值
见招拆招-第三式: typeof是—个关键字吗?
- typeof是GNU C编译器的特有关键字
- typeof只在 编译期生效 ,用于得到变量的类型
见招拆招-第四式 : 最后的原理
3、编程实验
container_of原理剖析 container of.c- #include <stdio.h>
- #ifndef offsetof
- #define offsetof(TYPE, MEMBER) ((size_t)&((TYPE*)0)->MEMBER)
- #endif
- #ifndef container_of
- #define container_of(ptr, type, member) ({ \
- const typeof(((type*)0)->member)* __mptr = (ptr); \
- (type*)((char*)__mptr - offsetof(type, member)); })
- #endif
- #ifndef container_of_new
- #define container_of_new(ptr, type, member) ((type*)((char*)(ptr) - offsetof(type, member)))
- #endif
- /* const typeof(((type*)0)->member)* __mptr = (ptr)的意义:做类型检查
- 在编译期编译器已知道member类型,不会在运行期访问0地址
- */
- struct ST
- {
- int i; // 0
- int j; // 4
- char c; // 8
- };
- void method_1()
- {
- int a = 0;
- int b = 0;
- int r = (
- a = 1,
- b = 2,
- a + b
- );
- printf("r = %d\n", r);
- }
- void method_2()
- {
- int r = ( {
- int a = 1;
- int b = 2;
- a + b;
- } );
- printf("r = %d\n", r);
- }
- void type_of()
- {
- int i = 100;
- typeof(i) j = i;
- const typeof(j)* p = &j;
- printf("sizeof(j) = %d\n", sizeof(j));
- printf("j = %d\n", j);
- printf("*p = %d\n", *p);
- }
- int main()
- {
- // method_1();
- // method_2();
- // type_of();
- struct ST s = {0};
- char* pc = &s.c;
- int e = 0;
- int* pe = &e;
- struct ST* pst = container_of(pc, struct ST, c);
- printf("&s = %p\n", &s);
- printf("pst = %p\n", pst);
- return 0;
- }
4、小结
编译器清楚的知道结构体成员变量的偏移位置
( { } )与逗号表达式类似,结果为最后—个语句的值
typeof只在编译期生效,用于得到变量的类型
container_of使用 ( { } ) 进行类型安全检查