OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 3605|回复: 18

结构体成员偏移值计算?求助

[复制链接]

14

主题

115

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
358
金钱
358
注册时间
2015-12-19
在线时间
307 小时
发表于 2016-9-13 21:36:03 | 显示全部楼层 |阅读模式
10金钱
原子有一篇帖子,讲的是宏定义来计算结构体成员的偏移值,印象中有这么一篇帖子,今天来找了半天,未果!!!特来求助,广大网友,帮忙寻找一下,十分感谢!!!

最佳答案

查看完整内容[请看2#楼]

了解container_of,就包含了offsetof的用法。 假设有个Struct,包含A成员,定义个p指针指向Strcut,将p指针的强行置0,那么p->A的就是offsetof的值。
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

4

主题

35

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
283
金钱
283
注册时间
2016-8-2
在线时间
13 小时
发表于 2016-9-13 21:36:04 | 显示全部楼层
shiqinghai 发表于 2016-9-14 23:21
额 我是想找原子的那篇文章,不是别的,印象中原子有一篇文章讲的就是结构体成员偏移的;
offsetof跟con ...

了解container_of,就包含了offsetof的用法。
假设有个Struct,包含A成员,定义个p指针指向Strcut,将p指针的强行置0,那么p->A的就是offsetof的值。
回复

使用道具 举报

6

主题

305

帖子

1

精华

金牌会员

Rank: 6Rank: 6

积分
2876
金钱
2876
注册时间
2016-7-17
在线时间
404 小时
发表于 2016-9-13 21:46:51 | 显示全部楼层
偏移值就是结构体每个成员占用的字节数啊,和你定义的数据类型有关,short=2,int=4,long long、double=8。
回复

使用道具 举报

14

主题

115

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
358
金钱
358
注册时间
2015-12-19
在线时间
307 小时
 楼主| 发表于 2016-9-13 21:51:04 | 显示全部楼层
f1174562 发表于 2016-9-13 21:46
偏移值就是结构体每个成员占用的字节数啊,和你定义的数据类型有关,short=2,int=4,long long、double=8 ...

对齐之后呢?
回复

使用道具 举报

69

主题

475

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1334
金钱
1334
注册时间
2013-12-28
在线时间
197 小时
发表于 2016-9-13 22:00:54 | 显示全部楼层
很显然 二楼说的不咋对
回复

使用道具 举报

6

主题

305

帖子

1

精华

金牌会员

Rank: 6Rank: 6

积分
2876
金钱
2876
注册时间
2016-7-17
在线时间
404 小时
发表于 2016-9-13 22:22:33 | 显示全部楼层

对齐?不明白,请闻其祥,求教!
回复

使用道具 举报

9

主题

538

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
3371
金钱
3371
注册时间
2015-1-7
在线时间
794 小时
发表于 2016-9-13 22:41:37 | 显示全部楼层

typedef struct _A
{
    char a;
    char b;
    int c;
    int d;
}A;

A tTest;
unsigned int offset;

offset = (unsigned int)&(tTest.c) - (unsigned int)&tTest;  //c在结构体中的偏移,不论是否对齐
机器生汇编,汇编生B,B生C,C生万物.... 经过长期对C语言的研究,目前只有两个方面不懂:这也不懂,那也不懂
https://github.com/ianhom
回复

使用道具 举报

4

主题

35

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
283
金钱
283
注册时间
2016-8-2
在线时间
13 小时
发表于 2016-9-13 22:53:14 | 显示全部楼层
在学习Linux驱动的过程中,遇到一个很好玩的内核函数,准确的说是一个很好玩的宏,叫做container_of。该宏定义在include/linux/kernel.h中,首先来贴出它的代码:

439/**
440 * container_of - cast a member of a structure out to the containing structure
441 * @ptr: the pointer to the member.
442 * @type: the type of the container struct this is embedded in.
443 * @member: the name of the member within the struct.
444 *
445 */
446#define container_of(ptr, type, member) ({ \
447 const typeof( ((type *)0)->member ) *__mptr = (ptr); \
448 (type *)( (char *)__mptr - offsetof(type,member) );})
它的作用显而易见,那就是根据一个结构体变量中的一个域成员变量的指针来获取指向整个结构体变量的指针。比如,有一个结构体变量,其定义如下:

struct demo_struct {
type1 member1;
type2 member2;
type3 member3;
type4 member4;
};
struct demo_struct demo;
同时,在另一个地方,获得了变量demo中的某一个域成员变量的指针,比如:

type3 *memp = get_member_pointer_from_somewhere();
此时,如果需要获取指向整个结构体变量的指针,而不仅仅只是其某一个域成员变量的指针,我们就可以这么做:

struct demo_struct *demop = container_of(memp, struct demo_struct, member3);
这样,我们就通过一个结构体变量的一个域成员变量的指针获得了整个结构体变量的指针。
下面说一说我对于这个container_of的实现的理解:
首先,我们将container_of(memp, struct demo_struct, type3)根据宏的定义进行展开如下:

struct demo_struct *demop = ({ \
const typeof( ((struct demo_struct *)0)->member3 ) *__mptr = (memp); \
(struct demo_struct *)( (char *)__mptr - offsetof(struct demo_struct, member3) );})
其中,typeof是GNU C对标准C的扩展,它的作用是根据变量获取变量的类型。因此,上述代码中的第2行的作用是首先使用typeof获取结构体域变量member3的类型为 type3,然后定义了一个type3指针类型的临时变量__mptr,并将实际结构体变量中的域变量的指针memp的值赋给临时变量__mptr。
假设结构体变量demo在实际内存中的位置如下图所示:
demo
+-------------+ 0xA000
| member1 |
+-------------+ 0xA004
| member2 |
| |
+-------------+ 0xA010
| member3 |
| |
+-------------+ 0xA018
| member4 |
+-------------+
则,在执行了上述代码的第2行之后__mptr的值即为0xA010。
再看上述代码的第3行,其中需要说明的是offsetof,它定义在include/linux/stddef.h中,其定义如下:

24#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
同样,我们将上述的offsetof调用展开,即为:

(struct demo_struct *)( (char *)__mptr - ((size_t) &((struct demo_struct *)0)->member3) );
可见,offsetof的实现原理就是取结构体中的域成员相对于地址0的偏移地址,也就是域成员变量相对于结构体变量首地址的偏移。
因此,offsetof(struct demo_struct, member3)调用返回的值就是member3相对于demo变量的偏移。结合上述给出的变量地址分布图可知,offsetof(struct demo_struct, member3)将返回0x10。
于是,由上述分析可知,此时,__mptr==0xA010,offsetof(struct demo_struct, member3)==0x10。
因此, (char *)__mptr - ((size_t) &((struct demo_struct *)0)->member3) == 0xA010 - 0x10 == 0xA000,也就是结构体变量demo的首地址(如上图所示)。
由此,container_of实现了根据一个结构体变量中的一个域成员变量的指针来获取指向整个结构体变量的指针的功能。
回复

使用道具 举报

14

主题

115

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
358
金钱
358
注册时间
2015-12-19
在线时间
307 小时
 楼主| 发表于 2016-9-13 23:27:51 | 显示全部楼层
f1174562 发表于 2016-9-13 22:22
对齐?不明白,请闻其祥,求教!

结构体对齐嘛
回复

使用道具 举报

14

主题

115

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
358
金钱
358
注册时间
2015-12-19
在线时间
307 小时
 楼主| 发表于 2016-9-13 23:28:42 | 显示全部楼层
chuyan 发表于 2016-9-13 22:53
在学习Linux驱动的过程中,遇到一个很好玩的内核函数,准确的说是一个很好玩的宏,叫做container_of。该宏 ...

麻烦发一下链接?
回复

使用道具 举报

14

主题

115

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
358
金钱
358
注册时间
2015-12-19
在线时间
307 小时
 楼主| 发表于 2016-9-13 23:28:54 | 显示全部楼层
ianhom 发表于 2016-9-13 22:41
typedef struct _A
{
    char a;

麻烦发一下链接?
回复

使用道具 举报

14

主题

115

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
358
金钱
358
注册时间
2015-12-19
在线时间
307 小时
 楼主| 发表于 2016-9-14 15:34:28 | 显示全部楼层
回复

使用道具 举报

8

主题

136

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
428
金钱
428
注册时间
2015-4-24
在线时间
85 小时
发表于 2016-9-14 15:40:28 | 显示全部楼层

我也不懂结构对齐是什么,求指教
回复

使用道具 举报

14

主题

115

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
358
金钱
358
注册时间
2015-12-19
在线时间
307 小时
 楼主| 发表于 2016-9-14 15:54:14 | 显示全部楼层
回复

使用道具 举报

4

主题

35

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
283
金钱
283
注册时间
2016-8-2
在线时间
13 小时
发表于 2016-9-14 23:05:44 | 显示全部楼层
shiqinghai 发表于 2016-9-13 23:28
麻烦发一下链接?

直接搜 container_of,就能找到相应结果。
回复

使用道具 举报

14

主题

115

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
358
金钱
358
注册时间
2015-12-19
在线时间
307 小时
 楼主| 发表于 2016-9-14 23:16:29 | 显示全部楼层
chuyan 发表于 2016-9-14 23:05
直接搜 container_of,就能找到相应结果。

论坛搜索代码,相当不好使。要不是报错,要不就搜索不到结果
回复

使用道具 举报

4

主题

35

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
283
金钱
283
注册时间
2016-8-2
在线时间
13 小时
发表于 2016-9-14 23:18:56 | 显示全部楼层
本帖最后由 chuyan 于 2016-9-14 23:20 编辑
shiqinghai 发表于 2016-9-14 23:16
论坛搜索代码,相当不好使。要不是报错,要不就搜索不到结果

http://blog.csdn.net/tigerjibo/article/details/8299589
参考这个链接,用法是已经结构体成员的指针,需要获取大结构体的指针方法。
回复

使用道具 举报

14

主题

115

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
358
金钱
358
注册时间
2015-12-19
在线时间
307 小时
 楼主| 发表于 2016-9-14 23:21:48 | 显示全部楼层
chuyan 发表于 2016-9-14 23:18
http://blog.csdn.net/tigerjibo/article/details/8299589

额 我是想找原子的那篇文章,不是别的,印象中原子有一篇文章讲的就是结构体成员偏移的;
offsetof跟container_of,这两个我知道咋个用法
回复

使用道具 举报

14

主题

115

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
358
金钱
358
注册时间
2015-12-19
在线时间
307 小时
 楼主| 发表于 2016-9-15 09:50:08 | 显示全部楼层
chuyan 发表于 2016-9-14 23:33
了解container_of,就包含了offsetof的用法。
假设有个Struct,包含A成员,定义个p指针指向Strcut,将p ...

算了,都不明白我什么意思,还是我慢慢找吧
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-5-25 09:56

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表