结构体的偏移量。在线等。

kobesff 2011-10-30 05:56:31
#include<stdio.h>
#include<stdlib.h>

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

struct test_struct{
char ch;
int it;
int ul;
};

int main()
{
size_t off=-1; //unsignde int -1=>10...01
struct test_struct *st,*rt;

st = (struct test_struct *) malloc (sizeof(struct test_struct));

st->ch='a';
st->it=1;
st->ul=1ul;

// off =(size_t)&(((struct test_struct *)0)->it);
off=offsetof(struct test_struct,it);

// rt=(struct test_struct *)((char *)(&st->it)-off);
rt=(struct test_struct *)(((char *)&(st->it)-(char *)off));

printf("%d %d %d",rt->it,off,sizeof(struct test_struct));


return 0;
}

1、求结构体的偏移量是什么意思?没看懂。运用在哪些地方?
2、这个宏没看明白。能详细解释下嘛?size_t 取值符号?
...全文
449 15 打赏 收藏 转发到动态 举报
写回复
用AI写文章
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
walq1222 2011-10-30
  • 打赏
  • 举报
回复
学习学习!!
编程点滴 2011-10-30
  • 打赏
  • 举报
回复
来学习的
kobesff 2011-10-30
  • 打赏
  • 举报
回复
[Quote=引用 11 楼 keiy 的回复:]

引用 9 楼 kobesff 的回复:
我查了下资料。好像说是如果结构体的最大类型<8 比如4. 那么char应该占4字节。

不知你的资料出处,它的前提什么?16位编译器,32位编译器是不一样的,单片机的更不用说了.,所以我说是与编译器有关的.
像你上面的程序,在DOS的BC下,结果为
1 1 5
因为它的编译器是1字节对齐的

语言的实现与平台有关的,从理论上讲,不能局限于某……
[/Quote]

结贴了。谢了。

我这样说的原因是发现VC下。设置#pragma pack(8)与设置#pragma pack(4)的效果是一样的。
  • 打赏
  • 举报
回复
详情请见《c与指针》10.3 结构的存储分配
柯本 2011-10-30
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 kobesff 的回复:]
我查了下资料。好像说是如果结构体的最大类型<8 比如4. 那么char应该占4字节。
[/Quote]
不知你的资料出处,它的前提什么?16位编译器,32位编译器是不一样的,单片机的更不用说了.,所以我说是与编译器有关的.
像你上面的程序,在DOS的BC下,结果为
1 1 5
因为它的编译器是1字节对齐的

语言的实现与平台有关的,从理论上讲,不能局限于某一平台.
当然,实际操作中是另一回事了


Lactoferrin 2011-10-30
  • 打赏
  • 举报
回复
offsetof就是实际偏移量
kobesff 2011-10-30
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 keiy 的回复:]
对齐方式是由编译器决定的
一般编译器可通过编译选项或#pragma来改变对齐方式的
如编译器对齐方式为8字节,而你的char只有一字节,那么在结构中,它就要占8字节
另一种情况,同样8字节对齐char[9],它要占16字节
[/Quote]
我查了下资料。好像说是如果结构体的最大类型<8 比如4. 那么char应该占4字节。而不是编译器的8字节?

另外rt是结构对象的首地址吧?不是实际偏移地址吧?
Lactoferrin 2011-10-30
  • 打赏
  • 举报
回复
还有理论偏移量和实际偏移量的区分?
柯本 2011-10-30
  • 打赏
  • 举报
回复
对齐方式是由编译器决定的
一般编译器可通过编译选项或#pragma来改变对齐方式的
如编译器对齐方式为8字节,而你的char只有一字节,那么在结构中,它就要占8字节
另一种情况,同样8字节对齐char[9],它要占16字节
kobesff 2011-10-30
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 keiy 的回复:]
1.结构体的偏移量是指结构中的成员在结构中的相对位置(有两个,下面有说明)
它的应用是可以通过指针直接访问结构体的成员(此时结构体的指针一般是与内存地址相对应,如操作系统编写,或网络协议的实现)
2.宏的展开
off=offsetof(struct test_struct,it);
==>off =(size_t)&(((struct test_struct *)0)->it); ……
[/Quote]
谢谢。还是有点不理解。

理论偏移和实际偏移什么时候情况下一致?。
是不是由编译器的字节对齐方式决定?当编译器字节对齐方式大于类型对齐方式最大值。
柯本 2011-10-30
  • 打赏
  • 举报
回复
1.结构体的偏移量是指结构中的成员在结构中的相对位置(有两个,下面有说明)
它的应用是可以通过指针直接访问结构体的成员(此时结构体的指针一般是与内存地址相对应,如操作系统编写,或网络协议的实现)
2.宏的展开
off=offsetof(struct test_struct,it);
==>off =(size_t)&(((struct test_struct *)0)->it);
得到变量it在结构struct test_struct 中的理论偏移量
但要注意的是,这个偏移量是指它前面的内容的长度,也就是 char ch;的理论长度而非it在struct test_struct 中的真实位置(由于编译器的对齐方式的关系)
rt=(struct test_struct *)((char *)(&st->it)-off);
==>rt=(struct test_struct *)(((char *)&(st->it)-(char *)off));
这个是指实际偏移量,也就是it在结构体中的实际位置
3. typedef unsigned int size_t;//size_t 就是unsigned int 类型
4.编译器的对齐方式可用
#pragma pack(n)
来改变,如,一个编译器是4字节对齐
上面的程序执行结果为
1 4 12
也就是说it在结构中理论位置为1,实际位置为4,结构的大小为12
实际上char ch占了4个字节
如果程序实上加
#pragma pack(1) //1个字节对齐
那程序的执行结果就为
1 1 9

ryfdizuo 2011-10-30
  • 打赏
  • 举报
回复
宏是取成员变量的地址。&取地址,然后将地址转化成size_t,即unsigned int。
结构体成员都是连续存储,需要考虑字节对齐情况。
Lactoferrin 2011-10-30
  • 打赏
  • 举报
回复
你想想如果把一个结构体放在0地址上,它的成员的地址是不是偏移量?
kobesff 2011-10-30
  • 打赏
  • 举报
回复
这题有点冷。
kobesff 2011-10-30
  • 打赏
  • 举报
回复
来着有分。尽量提示些盲点。别人没回答的。谢谢了。

69,382

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧