免费注册 查看新帖 |

Chinaunix

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

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

论坛徽章:
0
11 [报告]
发表于 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
12 [报告]
发表于 2009-05-18 09:59 |显示全部楼层

回复 #35 zx_wing 的帖子

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

论坛徽章:
0
13 [报告]
发表于 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]处开始。

论坛徽章:
0
14 [报告]
发表于 2009-05-18 10:06 |显示全部楼层
原帖由 zx_wing 于 2009-5-18 10:04 发表

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

据我所知,结构体内的域之间的padding不是ABI规定的,而是编译器的具体实现。

C89:
Each non-bit-field member of a structure or union object is aligned
in an implementation-defined manner appropriate to its type.

   Within a structure object, the non-bit-field members and the units
in which bit-fields reside have addresses that increase in the order
in which they are declared.  A pointer to a structure object, suitably
cast, points to its initial member (or if that member is a bit-field,
then to the unit in which it resides), and vice versa.  There may
therefore be unnamed holes within a structure object, but not at its
beginning, as necessary to achieve the appropriate alignment.

   The size of a union is sufficient to contain the largest of its
members.  The value of at most one of the members can be stored in a
union object at any time.  A pointer to a union object, suitably cast,
points to each of its members (or if a member is a bit-field, then to
the unit in which it resides), and vice versa.

   There may also be unnamed padding at the end of a structure or
union, as necessary to achieve the appropriate alignment were the
structure or union to be a member of an array.

论坛徽章:
0
15 [报告]
发表于 2009-05-18 10:13 |显示全部楼层
原帖由 zx_wing 于 2009-5-18 10:10 发表

嗯,现在像讲技术的态度了。
implementation-defined manner,确实是编译具体实现,但编译器的具体实现遵照的就是架构ABI。不论是编译器还是操作系统,都是必须遵照它。
implementation-defined manner 指就 ...

ABI主要控制的是操作系统与应用程序的系统调用的惯例,虽然在系统调用中如果传结构体参数,那么结构体必须遵照OS的ABI来控制padding,但是这并不是强制的。

论坛徽章:
0
16 [报告]
发表于 2009-05-18 10:15 |显示全部楼层
原帖由 zx_wing 于 2009-5-18 10:10 发表

嗯,现在像讲技术的态度了。
implementation-defined manner,确实是编译具体实现,但编译器的具体实现遵照的就是架构ABI。不论是编译器还是操作系统,都是必须遵照它。
implementation-defined manner 指就 ...

还有,我前面的代码能否解决你的问题?

论坛徽章:
0
17 [报告]
发表于 2009-05-18 10:17 |显示全部楼层

回复 #44 zx_wing 的帖子

所以即使是data[0]也是一样。

此外要改的彻底,packet*  cmd = malloc (sizeof(packet) + 20);直接改成packet*  cmd = malloc (offsetof(packet, data) + 20);

没错啊,我本来就是这个意思,gcc的data[0]的结构体的sizeof很诡异,就不应该用sizeof。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP