C语言笔记(结构体与offsetof、container_of之前的关系)
关于结构体学习,需要了解:结构体的定义和使用、内存对齐、结构体指针、得到结构体元素的偏移量(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之前的关系)的更多相关文章
- 瘋子C语言笔记(结构体/共用体/枚举篇)
(一)结构体类型 1.简介: 例: struct date { int month; int day; int year; }; struct student { int num; char name ...
- 01.C语言关于结构体的学习笔记
我对于学习的C语言的结构体做一个小的学习总结,总结如下: 结构体:structure 结构体是一种用户自己建立的数据类型,由不同类型数据组成的组合型的数据结构.在其他高级语言中称为记录(record) ...
- C语言链表结构体(学习笔记)
#include <stdio.h> #define LENTEST 100 // 采取逐步删除的方法求的素数 //先假设1-100都是素数,然后剔除2的倍数, //3的倍数,直到剔除所有 ...
- C语言中结构体对齐问题
C语言中结构体对齐问题 收藏 关于C语言中的结构体对齐问题 1,比如: struct{short a1;short a2;short a3;}A;struct{long a1;short a2;}B; ...
- C语言中结构体赋值问题的讨论
今天帮师姐调一个程序的BUG,师姐的程序中有个结构体直接赋值的语句,在我印象中结构体好像是不能直接赋值的,正如数组不能直接赋值那样,我怀疑这个地方有问题,但最后证明并不是这个问题.那么就总结一下C语言 ...
- C语言的结构体和C++结构体的区别
关于C++中声明结构体中需要使用构造器创建实例对象的语法: <C++的结构体构造方法的基本概念:结构体的构造方法需要和结构体的名字相同,并且无返回值,也不要void关键字,这样的方法就是构造器的 ...
- 逆向知识第十四讲,(C语言完结)结构体在汇编中的表现形式
逆向知识第十四讲,(C语言完结)结构体在汇编中的表现形式 一丶了解什么是结构体,以及计算结构体成员的对其值以及总大小(类也是这样算) 结构体的特性 1.结构体(struct)是由一系列具有相同类型或不 ...
- C语言中结构体赋值问题的讨论(转载)
今天帮师姐调一个程序的BUG,师姐的程序中有个结构体直接赋值的语句,在我印象中结构体好像是不能直接赋值的,正如数组不能直接赋值那样,我怀疑这个地方有问题,但最后证明并不是这个问题.那么就总结一下C语言 ...
- go语言学习-结构体
结构体 go语言中的结构体,是一种复合类型,有一组属性构成,这些属性被称为字段.结构体也是值类型,可以使用new来创建. 定义: type name struct { field1 type1 fie ...
- 将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. ...
随机推荐
- HDOJ 2081 手机短号
Problem Description 大家都知道,手机号是一个11位长的数字串,同时,作为学生,还可以申请加入校园网,如果加入成功,你将另外拥有一个短号.假设所有的短号都是是 6+手机号的后5位,比 ...
- String拼接也有用加号更好的时候
做String拼接时用StringBuilder(或StringBuffer)好还是直接用+号性能好?一般来说是前者,不过也有用加号略好的时候.首先我一直认为用+号有很好的可读性,而且当String拼 ...
- 《A First Course in Probability》-chape6-随机变量的联合分布-基本概念
之前我们探讨了一元随机变量的分布列,下面我们应该将相应的性质推广到多元随机变量的分布列,在这里我们主要以讨论二元随机变量分布列为主. 利用类比的方法,我们很容易将一元随机变量的分布列的性质推广上来. ...
- 借助github搭建自己的博客
创建GitHub技术博客全攻略 通过GitHub Pages建立个人站点(详细步骤) 备注: 我搭建成功了,但是访问时只能使用"http://username.github.io/usern ...
- Geometric Shapes (poj3449多边形相交)
题意:给你一些多边形的点,判断每个多边形和那些多边形相交,编号按照字典序输出 思路:枚举每个多边形的每条边看是否相交,这里的相交是包括端点的,关键是给你正方形不相邻两个点求另外两个点怎么求,长方形给你 ...
- Linux 相关scsi命令
Linux 相关scsi命令 由于前段时间存储扩容,对存储操作较多,下面记录了常用的操作: lsscsi命令:显示scsi设备信息 #lsscsi [0:0:0:2] disk IBM ...
- CCASS四种交收指令
CCASS 提供了4种类型的指令:ATI: Account Transfer Instruction 账户转移指令,用于本券商各个仓位上的转移STI: Stock Segregate Account ...
- eclipse下开发简单的Web Service
service部分 在eclipse下新建一个动态web项目 在项目中新建一个service类 编写SayHello类的代码 package org.sunny.service; //包不要引用错了 ...
- MVC 文件上传
项目需要,做一个图片上传的功能,本来是很简单,但是需要同时上传多个文件,并分条带一些额外的信息,听上去很复杂,通过下面图就可以一目了然: 网上找过一些方法,但多为不支持图片与其他信息关联,或者分两次上 ...
- 第四篇:SQL
前言 确实,关于SQL的学习资料,各类文档在网上到处都是.但它们绝大多数的出发点都局限在旧有关系数据库里,内容近乎千篇一律.而在当今大数据的浪潮下,SQL早就被赋予了新的责任和意义. 本篇中,笔者将结 ...