免费注册 查看新帖 |

Chinaunix

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

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

论坛徽章:
0
31 [报告]
发表于 2009-05-18 00:10 |只看该作者
原帖由 mik 于 2009-5-18 00:08 发表
跟他较劲,真没必要。

我都放弃了。

你就歇歇睡吧。

还是听你的。
我真是傻B了,还是不够淡定啊
就此打住,坚决不继续和他纠缠

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

>>LZ既然用到GCC的零长数组,就应该仔细阅读结构布局的说明。显然LZ没仔细搞清楚GCC的C扩展就乱用。
把你说的说明给我找出来,贴到这里。我倒是孤陋寡闻不清楚编译手册什么时候会规定架构ABI管的东西

>>要 ...

>>要是嫌阅读说明麻烦,把最后的data[0]改成data[1]不什么事都没了嘛。
给我讲讲data[1]有什么用。把内存布局画出来,证明这样改有用。
你要我说什么呢,按照你上面定义的结构,以X86的某个典型编译器为例,data[1]跟前面的char变量紧邻,但是整个结构的大小根据对齐原则data[0]的后面有两个字节的padding。

论坛徽章:
0
33 [报告]
发表于 2009-05-18 01:08 |只看该作者
几位都是高手。相互争论一下也没什么不可以的,相反更有利于真相的出现。
问题弄明白目的就达到了。最重要的是我等小辈又长见识了,又能认识到自己的不足。
希望能向大佬们学习。

论坛徽章:
0
34 [报告]
发表于 2009-05-18 08:58 |只看该作者
呵呵,装B被雷劈

论坛徽章:
0
35 [报告]
发表于 2009-05-18 09:07 |只看该作者
原帖由 yhb04 于 2009-5-18 00:17 发表

>>要是嫌阅读说明麻烦,把最后的data[0]改成data[1]不什么事都没了嘛。
给我讲讲data[1]有什么用。把内存布局画出来,证明这样改有用。
你要我说什么呢,按照你上面定义的结构,以X86的某个典型编译器为例, ...

呵呵,data[0]也和前面的紧邻的
如果仅仅是malloc(sizeof(packet)),则data[1]情况变为:
head (4 bytes) size (4 bytes) reply (1 byte) data[1] (1 bytes) padding (2 bytes)
如果是data[0]:
head (4 bytes) size (4 bytes) reply (1 byte) data[0] (0 bytes) padding (3 bytes)

不管data[0],data[1],malloc(sizeof(packet) + 20)后,之后都没有padding。所以两者内存布局本质是一样的,把data[0]改成data[1]没有任何帮助。


你跟我讲技术,我就心平气和的给你讲

[ 本帖最后由 zx_wing 于 2009-5-18 09:12 编辑 ]

论坛徽章:
0
36 [报告]
发表于 2009-05-18 09:55 |只看该作者
原帖由 zx_wing 于 2009-5-18 09:07 发表

呵呵,data[0]也和前面的紧邻的
如果仅仅是malloc(sizeof(packet)),则data[1]情况变为:
head (4 bytes) size (4 bytes) reply (1 byte) data[1] (1 bytes) padding (2 bytes)
如果是data[0]:
head (4  ...

谁说内存内存布局不一样了,只是改成data[1]啥的就可以正确求的offset(data,packet)的值了。
gcc的data[0]的实现就比较诡异了,实际应用中用这个东西是为了应付变长结构,这个时候使用sizeof(packet)是不适宜的,因为它考虑了结构末尾的padding。
我本来说了C99里面的data[]满足你的要求。

C99:
16 As a special case, the last element of a structure with more than one named member may
have an incomplete array type; this is called a flexible array member. With two
exceptions, the flexible array member is ignored. First, the size of the structure shall be
equal to the offset of the last element of an otherwise identical structure that replaces the
flexible array member with an array of unspecified length.106) Second, when a . (or ->)
operator has a left operand that is (a pointer to) a structure with a flexible array member
and the right operand names that member, it behaves as if that member were replaced
with the longest array (with the same element type) that would not make the structure
larger than the object being accessed; the offset of the array shall remain that of the
flexible array member, even if this would differ from that of the replacement array. If this
array would have no elements, it behaves as if it had one element but the behavior is
undefined if any attempt is made to access that element or to generate a pointer one past
it.
17 EXAMPLE Assuming that all array members are aligned the same, after the declarations:
struct s { int n; double d[]; };
struct ss { int n; double d[1]; };
the three expressions:
sizeof (struct s)
offsetof(struct s, d)
offsetof(struct ss, d)
have the same value. The structure struct s has a flexible array member d.

PS:如果你不和俺抬杠,俺也可以心平气和的和你谈。

论坛徽章:
0
37 [报告]
发表于 2009-05-18 09:59 |只看该作者

回复 #35 zx_wing 的帖子

还有,这个问题本身跟各个平台的ABI没有太大关系。
我只假设你在X86平台上用gcc编译2个程序,互相通信。
如果你说你的一个程序是X86的gcc编译的程序,另一个是其他平台其他编译器编译的程序。那当我前面什么都没说。

论坛徽章:
0
38 [报告]
发表于 2009-05-18 10:03 |只看该作者
原帖由 yhb04 于 2009-5-18 09:55 发表

谁说内存内存布局不一样了,只是改成data[1]啥的就可以正确求的offset(data,packet)的值了。
gcc的data[0]的实现就比较诡异了,实际应用中用这个东西是为了应付变长结构,这个时候使用sizeof(packet)是不适宜 ...

》》只是改成data[1]啥的就可以正确求的offset(data,packet)的值了、
data[0],data[1]通过offsetof求值是一样的,因为它们之前的内存布局相同

论坛徽章:
0
39 [报告]
发表于 2009-05-18 10:04 |只看该作者
原帖由 yhb04 于 2009-5-18 09:59 发表
还有,这个问题本身跟各个平台的ABI没有太大关系。
我只假设你在X86平台上用gcc编译2个程序,互相通信。
如果你说你的一个程序是X86的gcc编译的程序,另一个是其他平台其他编译器编译的程序。那当我前面什么都 ...

当然有关系。如果ABI规定padding在reply之后data之前,结果就完全不一样

论坛徽章:
0
40 [报告]
发表于 2009-05-18 10:05 |只看该作者
原帖由 zx_wing 于 2009-5-18 10:03 发表

》》只是改成data[1]啥的就可以正确求的offset(data,packet)的值了、
data[0],data[1]通过offsetof求值是一样的,因为它们之前的内存布局相同

typedef struct {
        int head;
        int size; //指明整个包的长度
     char reply;
        char data[1];
} packet;

packet*  cmd = malloc (sizeof(packet) + 20); //多空几个字节无所谓
memcpy (packet->data, some_data, 20);

#define offsetof(type, element) ((unsigned long)&((type *)0)->element)
cmd->size = offsetof(packet, data) + 20;//cmd->size的计算不要用sizeof(packet)



static inline size_t packet_data_len(packet* cmd) {
    assert(cmd);
    return cmd->size - offsetof(packet, data);
}

memcpy (buffer_to_receive_data, cmd->data, packet_data_len (cmd));




或者直接用cmd->size记录实际数据的长度,数据在cmd->data[0]处开始。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP