免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: zx_wing
打印 上一主题 下一主题

char[0], sizeof和struct padding [复制链接]

论坛徽章:
3
天蝎座
日期:2014-10-25 13:44:312015年辞旧岁徽章
日期:2015-03-03 16:54:152015年迎新春徽章
日期:2015-03-04 09:48:31
11 [报告]
发表于 2009-05-17 20:24 |只看该作者
好帖子;


一般都是不吃亏不长记性的。

就像新员工来后,很鄙视我们代码中的一些做法,认为这个那个运行效率低,

搞了几次,出了几个BUG后,就知道学乖了。

当然,楼主肯定是个老鸟,不是新员工。

论坛徽章:
0
12 [报告]
发表于 2009-05-17 21:03 |只看该作者
char data[0];

改为: char*data

应该没有问题

论坛徽章:
0
13 [报告]
发表于 2009-05-17 22:29 |只看该作者
原帖由 yhb04 于 2009-5-17 19:11 发表
typedef struct {
        int head;
        int size; //指明整个包的长度
     char reply;
        char data[1];
} packet;

packet*  cmd = malloc (sizeof(packet) + 20); //多空几个字节无所谓
...

呵呵,小伙子水平不高口气不小。
首先char data[1]解决不了问题,char data[0]不是C标准,前者是C标准而已。
其次,gcc手册没有对零长数组有太多解释,这本来就是个简单的东西。其次这里的内存布局和是不是零长数组没有关系,把char data[0]换成char data是一样。不过你还是说对了,这是内存布局的问题引起的,具体的说着取决于padding的位置。我怀疑你是猜的,因为编译手册是不会讲这个内存布局的,不同的架构对padding有不同的规定。这个是架构的ABI或software conventions规定的。例如

  1. struct example {
  2.         int a;
  3.         int b;
  4.         char c;
  5.         char d;
  6. };

  7. sizeof (struct example) == 12;
  8. offsetof (struct example, d) == 9;
复制代码

恍然一看似乎offsetof在计算偏移的时候没有算padding,实际不然,padding在最后两个字节,所以上面例子的内存布局是:
a(4 bytes) b(4 bytes) c(1 byte) d(1 byte) padding (2 bytes)
对于我用的 x86平台,这个其在ABI手册有规定:
Each member is assigned to the lowest available offset with the appropriate
alignment. This may require internal padding, depending on the previous
member.

这里d前面的c同样是char类型,所以两者之间没有padding,而根据另一条规定:
A structure¡¯s size is increased, if necessary, to make it a multiple of the
alignment. This may require tail padding, depending on the last member.

把padding放在了最后,即tail padding。

如果有一种架构使用不同的padding方式,例如:
a(4 bytes) b(4 bytes) c(1 byte) padding (1 byte) d(1 byte) padding (1 byte)
则offsetof (struct example, d) == 10;
gcc关于零长数组的章节有点长,并且和这里的内容没有什么关系,就不贴了。我估计你也没看过,它的标题是“5.14 Arrays of Length Zero”,不信你可以去看看。

[ 本帖最后由 zx_wing 于 2009-5-17 23:15 编辑 ]

论坛徽章:
0
14 [报告]
发表于 2009-05-17 22:50 |只看该作者

回复 #13 zx_wing 的帖子

zx_wing 就别和他较劲了。正如你说他的:水平不高口气不小。
偶领教过,说话牛哄哄的,特拽

论坛徽章:
0
15 [报告]
发表于 2009-05-17 23:17 |只看该作者
如果是我,我会分为消息头和数据两部分

论坛徽章:
0
16 [报告]
发表于 2009-05-17 23:29 |只看该作者
原帖由 baicj 于 2009-5-17 19:58 发表

如同你所说, 问题在于daemon端用sizeof计算的struct head大小, 而library端用offsetof计算struct head大小, 两者结果不一致. 修改位data[1]不会有帮助, 解决问题的办法也正如你的代码, 统一用offsetof来代替s ...

是的,关键问题在于offsetof和sizeof计算得来head大小不一样。
我刚才google了一下发现问这个问题的人还很多,但没人回答,下面这个帖子里的老外就以为对齐出错了:
http://connect.microsoft.com/Vis ... x?FeedbackID=253387

实际上问题仅仅是我们错误的假设的padding的位置而已。

论坛徽章:
0
17 [报告]
发表于 2009-05-17 23:31 |只看该作者
原帖由 mik 于 2009-5-17 22:50 发表
zx_wing 就别和他较劲了。正如你说他的:水平不高口气不小。
偶领教过,说话牛哄哄的,特拽

呵呵,也不是较劲。只是借着话题顺便把问题讲清楚了,供遇到同样问题或以后遇到同样问题的朋友借鉴。

论坛徽章:
0
18 [报告]
发表于 2009-05-17 23:33 |只看该作者
原帖由 zx_wing 于 2009-5-17 22:29 发表

呵呵,小伙子水平不高口气不小。
首先char data[1]解决不了问题,char data[0]不是C标准,前者是C标准而已。
其次,gcc手册没有对零长数组有太多解释,这本来就是个简单的东西。其次这里的内存布局和是不是 ...

猜不猜不是你说了算,现在写一个C编译器也不是天方夜谈,你对结构体的布局不了解并不表示别人也这样。装B不是靠发帖数多。您爱装就继续装吧。
对了,GCC的零长数组满足不了您的需求,倒是C99 里的东西可以符合你的要求。不过现在不知道有那个编译器是些了它没有。

论坛徽章:
0
19 [报告]
发表于 2009-05-17 23:38 |只看该作者
原帖由 mik 于 2009-5-17 22:50 发表
zx_wing 就别和他较劲了。正如你说他的:水平不高口气不小。
偶领教过,说话牛哄哄的,特拽

还有你,倒是真的水平不高,口气不小。
上次花了1个小时还找了个错误的源文件
论抬杠您水平确实不赖。有个版主头衔说话就这么吊。

论坛徽章:
0
20 [报告]
发表于 2009-05-17 23:42 |只看该作者
学习,lz的贴都是好贴
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP