zoukankan      html  css  js  c++  java
  • C语言笔记(结构体与offsetof、container_of之前的关系)

    关于结构体学习,需要了解:结构体的定义和使用、内存对齐、结构体指针、得到结构体元素的偏移量(offsetof宏实现)

    一、复习结构体的基本定义和使用

     1 typedef struct mystruct
     2 {
     3     int a;
     4     char b;
     5     double c;
     6 }MyS1;
     7 
     8 /*
     9     函数功能:演示结构体的定义和使用
    10 */
    11 void func1(void)
    12 {
    13     //定义时赋值
    14     MyS1 s1 = {
    15         .a =1,
    16         .b =2,
    17         .c = 1.23,
    18     };
    19     printf("s1.a = %d.
    ", s1.a);
    20     printf("s1.b = %d.
    ", s1.b);
    21     printf("s1.c = %f.
    ", s1.c);
    22     printf("value is change.
    ");
    23     // 使用.访问方式赋值
    24     s1.a = 123;
    25     s1.b = 4;
    26     s1.c = 3.12;
    27     
    28     printf("s1.a = %d.
    ", s1.a);
    29     printf("s1.b = %d.
    ", s1.b);
    30     printf("s1.c = %f.
    ", s1.c);
    31 }

    结果:

    分析:主要是复习一下结构体的定义和使用。

    二、结构体指针的使用

     1 typedef struct mystruct
     2 {
     3     int a;
     4     char b;
     5     double c;
     6 }MyS1;
     7 /*
     8     函数功能:演示结构体指针的使用
     9 */
    10 void func2(MyS1 *s_temp)
    11 {
    12     s_temp->a = 12;
    13     s_temp->b = 34;
    14     s_temp->c = 56.123;
    15     printf("s_temp->a = %d.
    ", s_temp->a);
    16     printf("s_temp->a = %d.
    ", s_temp->b);
    17     printf("s_temp->a = %f.
    ", s_temp->c);
    18 }
    19 int main(void)
    20 {
    21     MyS1 s1;
    22     MyS1 *ps1 = &s1;
    23     func2(ps1);
    24     return 0;
    25 }

    结果:

    三、offsetof宏详解

    先看看代码,是如何使用offsetof的

    1 #define offsetof(TYPE, MEMBER)  ((int) &((TYPE *)0)->MEMBER)
    2 
    3 struct mystruct
    4 {
    5     int a;
    6     char b;
    7     double c;
    8 };
    9 int adr_a = offsetof(struct mystruct, b); // adr_a = 4

    offsetof宏的分析: #define offsetof(TYPE, MEMBER)  ((int) &((TYPE *)0)->MEMBER)
     1、功能:返回结构体元素的相对结构体首地址的偏移
     2、参数:TYPE是结构体类型,MEMBER是结构体中一个元素的元素名

     3、分析:
        (1) (TYPE *)0;  将0转换成结构体指针;
        (2) ((TYPE *)0)->MEMBER; 使用指针方式访问结构体中元素
        (3) &(((TYPE *)0)->MEMBER);  取结构体中元素的地址
        (4) (int) &(((TYPE *)0)->MEMBER); 转换成int型返回

    四、container_of宏详解

    先看代码

     1 #define container_of(ptr, type, member) ({  
     2    const typeof(((type *)0)->member) * __mptr = (ptr); 
     3    (type *)((char *)__mptr - offsetof(type, member));})
     4 
     5 typedef struct mystruct
     6 {
     7     int a;
     8     char b;
     9     double c;
    10 }MyS1;
    11 struct mystruct s1;
    12 MyS1 *ps = NULL;
    13 double *p = &s1.c;
    14 printf("&s1 = %p.
    " ,&s1);
    15 
    16 ps = container_of(p, MyS1, c);
    17 printf("ps  = %p.
    " ,ps);

    结果:

    分析:根据&s1.c的地址得到整个结构体的首地址

    详解:

    #define container_of(ptr, type, member) ({ 
       const typeof(((type *)0)->member) * __mptr = (ptr);
       (type *)((char *)__mptr - offsetof(type, member));})

     1、功能:返回整个结构体变量的指针
     2、参数:
    ptr是指向结构体中一个元素的指针;type是结构体类型;member是结构体中一个元素的元素名

     3、分析:
        (1) typeof(((type *)0)->member); 获取结构体中一个元素的类型;s1.c 的类型是double
        (2) const typeof(((type *)0)->member) * __mptr = (ptr); 
            就可以理解为:
            const double * __mptr = (ptr);//__mptr指向ptr处
        (3) (char *)__mptr - offsetof(type, member); // 结构体其中一个元素的地址 - 该元素相对结构体首地址的偏移
        (4) (type *)((char *)__mptr - offsetof(type, member)); // 转换成该结构体类型的指针返回

    -----------------------------------------------------------------------------------------------------------------------------------

    注:以上程序是参考“朱老师物联网视频”中的代码,特此申明!

    ----------------------------------------------------------------------------------------------------------------------------

  • 相关阅读:
    Oracle SQL语句大全—查看表空间
    Class to disable copy and assign constructor
    在moss上自己总结了点小经验。。高手可以飘过 转贴
    在MOSS中直接嵌入ASP.NET Page zt
    Project Web Access 2007自定义FORM验证登录实现 zt
    SharePoint Portal Server 2003 中的单一登录 zt
    vs2008 开发 MOSS 顺序工作流
    VS2008开发MOSS工作流几个需要注意的地方
    向MOSS页面中添加服务器端代码的另外一种方式 zt
    状态机工作流的 SpecialPermissions
  • 原文地址:https://www.cnblogs.com/zou107/p/4950936.html
Copyright © 2011-2022 走看看