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

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

 typedef struct mystruct
{
int a;
char b;
double c;
}MyS1; /*
函数功能:演示结构体的定义和使用
*/
void func1(void)
{
//定义时赋值
MyS1 s1 = {
.a =,
.b =,
.c = 1.23,
};
printf("s1.a = %d.\n", s1.a);
printf("s1.b = %d.\n", s1.b);
printf("s1.c = %f.\n", s1.c);
printf("value is change.\n");
// 使用.访问方式赋值
s1.a = ;
s1.b = ;
s1.c = 3.12; printf("s1.a = %d.\n", s1.a);
printf("s1.b = %d.\n", s1.b);
printf("s1.c = %f.\n", s1.c);
}

结果:

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

二、结构体指针的使用

 typedef struct mystruct
{
int a;
char b;
double c;
}MyS1;
/*
函数功能:演示结构体指针的使用
*/
void func2(MyS1 *s_temp)
{
s_temp->a = ;
s_temp->b = ;
s_temp->c = 56.123;
printf("s_temp->a = %d.\n", s_temp->a);
printf("s_temp->a = %d.\n", s_temp->b);
printf("s_temp->a = %f.\n", s_temp->c);
}
int main(void)
{
MyS1 s1;
MyS1 *ps1 = &s1;
func2(ps1);
return ;
}

结果:

三、offsetof宏详解

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

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

 struct mystruct
{
int a;
char b;
double c;
};
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宏详解

先看代码

 #define container_of(ptr, type, member) ({  \
const typeof(((type *))->member) * __mptr = (ptr); \
(type *)((char *)__mptr - offsetof(type, member));}) typedef struct mystruct
{
int a;
char b;
double c;
}MyS1;
struct mystruct s1;
MyS1 *ps = NULL;
double *p = &s1.c;
printf("&s1 = %p.\n" ,&s1); ps = container_of(p, MyS1, c);
printf("ps = %p.\n" ,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)); // 转换成该结构体类型的指针返回

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

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

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

C语言笔记(结构体与offsetof、container_of之前的关系)的更多相关文章

  1. 瘋子C语言笔记(结构体/共用体/枚举篇)

    (一)结构体类型 1.简介: 例: struct date { int month; int day; int year; }; struct student { int num; char name ...

  2. 01.C语言关于结构体的学习笔记

    我对于学习的C语言的结构体做一个小的学习总结,总结如下: 结构体:structure 结构体是一种用户自己建立的数据类型,由不同类型数据组成的组合型的数据结构.在其他高级语言中称为记录(record) ...

  3. C语言链表结构体(学习笔记)

    #include <stdio.h> #define LENTEST 100 // 采取逐步删除的方法求的素数 //先假设1-100都是素数,然后剔除2的倍数, //3的倍数,直到剔除所有 ...

  4. C语言中结构体对齐问题

    C语言中结构体对齐问题 收藏 关于C语言中的结构体对齐问题 1,比如: struct{short a1;short a2;short a3;}A;struct{long a1;short a2;}B; ...

  5. C语言中结构体赋值问题的讨论

    今天帮师姐调一个程序的BUG,师姐的程序中有个结构体直接赋值的语句,在我印象中结构体好像是不能直接赋值的,正如数组不能直接赋值那样,我怀疑这个地方有问题,但最后证明并不是这个问题.那么就总结一下C语言 ...

  6. C语言的结构体和C++结构体的区别

    关于C++中声明结构体中需要使用构造器创建实例对象的语法: <C++的结构体构造方法的基本概念:结构体的构造方法需要和结构体的名字相同,并且无返回值,也不要void关键字,这样的方法就是构造器的 ...

  7. 逆向知识第十四讲,(C语言完结)结构体在汇编中的表现形式

    逆向知识第十四讲,(C语言完结)结构体在汇编中的表现形式 一丶了解什么是结构体,以及计算结构体成员的对其值以及总大小(类也是这样算) 结构体的特性 1.结构体(struct)是由一系列具有相同类型或不 ...

  8. C语言中结构体赋值问题的讨论(转载)

    今天帮师姐调一个程序的BUG,师姐的程序中有个结构体直接赋值的语句,在我印象中结构体好像是不能直接赋值的,正如数组不能直接赋值那样,我怀疑这个地方有问题,但最后证明并不是这个问题.那么就总结一下C语言 ...

  9. go语言学习-结构体

    结构体 go语言中的结构体,是一种复合类型,有一组属性构成,这些属性被称为字段.结构体也是值类型,可以使用new来创建. 定义: type name struct { field1 type1 fie ...

  10. 将c语言的结构体定义变成对应的golang语言的结构体定义,并将golang语言结构体变量的指针传递给c语言,cast C struct to Go struct

    https://groups.google.com/forum/#!topic/golang-nuts/JkvR4dQy9t4 https://golang.org/misc/cgo/gmp/gmp. ...

随机推荐

  1. cf702D Road to Post Office

    D. Road to Post Office time limit per test 1 second memory limit per test 256 megabytes input standa ...

  2. 《ACM国际大学生程序设计竞赛题解I》——6.10

    Pku 1143: Description Christine and Matt are playing an exciting game they just invented: the Number ...

  3. F - Wormholes

    题目大意: 农民约翰在农场散步的时候发现农场有大量的虫洞,这些虫洞是非常特别的因为它们都是单向通道,为了方便现在把约翰的农田划分成N快区域,M条道路,W的虫洞. 约翰是时空旅行的粉丝,他希望这样做,在 ...

  4. 区别assign VS weak,__block VS __weak

    在objective-c中,类中的全局变量经常使用如下的方式申明. @property(nonatomic(1),strong(2))UIImageView *imageView; 其中的1,2处是对 ...

  5. js点击弹出div层

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  6. JAX-WS + Spring 开发webservice

    通过几天的时间研究了下使用jax-ws来开发webservice,看了网上的一些资料总结出jax-ws的开发大概分为两种. 以下项目使用的spring3.0,jar包可以到官网下载 第一种:使用独立的 ...

  7. Reso | The Linux Command Line 的中文版

    http://book.haoduoshipin.com/tlcl/book/zh/ 本书是 The Linux Command Line 的中文版, 为大家提供了多种不同的阅读方式. 中英文双语版- ...

  8. 安卓扫码:简单的ZXing使用记录

    ZXing是Google提供的条形码.二维码等的生成.解析的库.最近工作需求去研究了一下,主要是研究怎么扫描二维码(QRCode).网上教程也不少,但大多看了不明所以,甚至看了半天都不知道解码到底从哪 ...

  9. HUD2087

    #include<iostream> #include<cstdio> #include<cstring> #define maxn 1010 using name ...

  10. 重装系统时,将MBR分区转为GPT 分区

    摘要 很多同学在重装系统的时候,或多或少都遇到过这样的问题:镜像文件没有问题,软碟通刻录也没有问题,但偏偏就在选择安装系统盘盘符的时候,跳出对话框,提示:Windows无法安装到这个磁盘,选中的磁盘具 ...