第31课 - 老生常谈的两个宏(Linux)

1、老生常谈的两个宏(Linux)

        Linux内核中常用的两个宏定义 

    

        见招拆招-第—式:谝译器做了什么? 

                offsetof用于计算TYPE结构体中MEMBER成员的偏移位置 




2、编程实验 

扫描二维码关注公众号,回复: 890009 查看本文章
offsetof原理剖析     offsetof.c

  1. #include <stdio.h>  
  2.   
  3. #ifndef offsetof  
  4. #define offsetof(TYPE, MEMBER) ((size_t)&((TYPE*)0)->MEMBER)    //根本不会访问0地址处,只是做加法  
  5. #endif  
  6.   
  7.   
  8. struct ST  
  9. {  
  10.     int i;     // 0  
  11.     int j;     // 4  
  12.     char c;    // 8  
  13. };  
  14.   
  15. void func(struct ST* pst)  
  16. {  
  17.     int* pi = &(pst->i);    //  0  
  18.     int* pj = &(pst->j);    //  4  
  19.     char* pc = &(pst->c);   //  8  
  20.   
  21.     printf("pst = %p\n", pst);  
  22.     printf("pi = %p\n", pi);  
  23.     printf("pj = %p\n", pj);  
  24.     printf("pc = %p\n", pc);  
  25. }  
  26.   
  27. int main()  
  28. {  
  29.     struct ST s = {0};  
  30.   
  31.     func(&s);  
  32.     func(NULL);  
  33.   
  34.     printf("offset i: %d\n", offsetof(struct ST, i));  
  35.     printf("offset j: %d\n", offsetof(struct ST, j));  
  36.     printf("offset c: %d\n", offsetof(struct ST, c));  
  37.   
  38.     return 0;  
  39. }  

                


            见招拆招-第二式: 

                    ( { } ) 是何方神圣? 

                                - ( { } )GNU C编译器的语法扩展 

                                - ( { } ) 与逗号表达式类似, 结果为最后—个语句的值 

        


            见招拆招-第三式: typeof是—个关键字吗? 

                    - typeofGNU C编译器的特有关键字 

                    - typeof只在 编译期生效 ,用于得到变量的类型

            


            见招拆招-第四式 : 最后的原理 



3、编程实验 

container_of原理剖析     container of.c

  1. #include <stdio.h>  
  2.   
  3. #ifndef offsetof  
  4. #define offsetof(TYPE, MEMBER) ((size_t)&((TYPE*)0)->MEMBER)  
  5. #endif  
  6.   
  7. #ifndef container_of  
  8. #define container_of(ptr, type, member) ({               \  
  9.         const typeof(((type*)0)->member)* __mptr = (ptr);   \  
  10.         (type*)((char*)__mptr - offsetof(type, member)); })  
  11. #endif  
  12.   
  13. #ifndef container_of_new  
  14. #define container_of_new(ptr, type, member) ((type*)((char*)(ptr) - offsetof(type, member)))  
  15. #endif  
  16.   
  17.   
  18.  /* const typeof(((type*)0)->member)* __mptr = (ptr)的意义:做类型检查 
  19.     
  20.    在编译期编译器已知道member类型,不会在运行期访问0地址 
  21.  
  22.     */  
  23.   
  24. struct ST  
  25. {  
  26.     int i;     // 0  
  27.     int j;     // 4  
  28.     char c;    // 8  
  29. };  
  30.   
  31. void method_1()  
  32. {  
  33.     int a = 0;  
  34.     int b = 0;  
  35.   
  36.     int r = (  
  37.            a = 1,  
  38.            b = 2,  
  39.            a + b  
  40.                 );  
  41.   
  42.     printf("r = %d\n", r);  
  43. }  
  44.   
  45. void method_2()  
  46. {  
  47.     int r = ( {  
  48.                   int a = 1;  
  49.                   int b = 2;  
  50.   
  51.                   a + b;  
  52.               } );  
  53.   
  54.     printf("r = %d\n", r);  
  55. }  
  56.   
  57. void type_of()  
  58. {  
  59.     int i = 100;  
  60.     typeof(i) j = i;  
  61.     const typeof(j)* p = &j;  
  62.   
  63.     printf("sizeof(j) = %d\n"sizeof(j));  
  64.     printf("j = %d\n", j);  
  65.     printf("*p = %d\n", *p);  
  66. }  
  67.   
  68. int main()  
  69. {  
  70.   
  71.     // method_1();  
  72.     // method_2();  
  73.     // type_of();  
  74.   
  75.     struct ST s = {0};  
  76.     char* pc = &s.c;  
  77.     int e = 0;  
  78.     int* pe = &e;  
  79.   
  80.     struct ST* pst = container_of(pc, struct ST, c);  
  81.       
  82.       
  83.   
  84.     printf("&s = %p\n", &s);  
  85.     printf("pst = %p\n", pst);  
  86.   
  87.     return 0;  
  88. }  


                        


4、小结 

            编译器清楚的知道结构体成员变量的偏移位置 

            ( { } )与逗号表达式类似,结果为最后—个语句的值 

            typeof只在编译期生效,用于得到变量的类型 

             container_of使用 ( { } ) 进行类型安全检查


猜你喜欢

转载自blog.csdn.net/qq_39654127/article/details/80272343