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)); // 转换成该结构体类型的指针返回

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

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

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

  • 相关阅读:
    spring cloud-之入门技术选型的抉择
    jvm系列之-gc日志查看
    jvm系列之-参数设置
    Code completion has become quite slow under Delphi7
    Python4Delphi注意事项
    SHFileOperation删除文件夹
    开漏输出,推挽输出
    DxGrexpt中的ExcelFormat (BIFF)
    通过exe名字查询句柄,String与ShortString转换函数分析
    Netstat判断商品是否正在使用
  • 原文地址:https://www.cnblogs.com/zou107/p/4950936.html
Copyright © 2011-2022 走看看