用C

问题描述:

类型转换更大或更小结构我在C程序两种结构: SmallStructABC和BigStructXYZ用C

我在两者的几个成员; SmallStructABC的所有10个成员与BigStructXYZ的前10名成员完全相同。 BigStructXYZ有50个额外的成员。

将这两个结构键入对方可以吗?

SmallStructABC *i = (BigStructXYZ*)j; 
BigStructXYZ *a = (SmallStructABC*)b; 

我只能访问第10(普通)会员类型转换后..

我写的C程序,我的机器上它的工作的罚款。只是想验证是否需要照顾任何角落的情况下(对齐,无效阅读,非GCC汇编等)..

编辑: 问:为什么我想要做这样的事情? A:BigStructXYZ的大小非常大(比如50KB)并且包含一些标题(键,地图等)。 我在通过网络发送之前压缩此数据。我保留标题(在我们的例子中是SmallStructABC)。 通过进行类型转换,我可以在需要时从标题访问这些键。

+1

你为什么要这样做?顺便说一句,看看工会,也许他们是你的解决方案? – 2009-12-28 04:22:37

+2

不要那样做。将*指针指向结构* – 2009-12-28 04:26:02

+0

@Jack - 不要忘记实际接受您收到答案的那些问题的答案。 – 2009-12-28 05:08:44

不,这不是一个好主意。更好的是通过指针类型转换指针的结构和操作它们:

void DoSomething(Small *thing) { 
    // ... 
} 

int main() { 
    Big big = {0}; 
    Small small = {0}; 

    Small *p0 = (Small*)&big; 
    Small *p1 = &small; 

    DoSomething(p0); 
    DoSomething(p1); 

    return 0; 
} 

另一种更安全的设计是在Small来定义Big

typedef struct Small { 
    int foo; 
}; 
typedef struct Big { 
    Small small; 
    int y; 
}; 
+0

我同意这个答案为我的问题。虽然我的设计有点复杂,但这可能不会马上起作用。 小和大都有他们共同的前10名成员和小共有20名成员和大有50名成员。 人们会问,为什么不把前10个成员作为独立结构并包含它?我同意.. 感叹!这不是一个选项:( – Jack 2009-12-29 04:38:15

+0

那么我首先给出了指针解决方案,因为我明白某些设计不能改变,但是来吧,这是C,你的设计不能(不应该)变得复杂: ) – 2009-12-29 04:40:36

+0

我完全同意... 但是,改变这种结构不在我的手中.. – Jack 2009-12-29 05:14:20

上面的代码不会编译。 j已经是BigStructXYZ了,你的意思是把它投射到SmallStructABC?

无论如何,你试图做的是一个坏主意。将SmallStructXYZ作为BigStructXYZ内部的第一个字段并因此工作会更好:

SmallStructABC i = j.smallStruct; 
BigStructXYZ a = { b }; 

我可以想想这种情况下,不能保证我的头顶上的工作,但它应该在大多数平台大多数情况下罚款。一个我想到的是,我认为对齐应该由结构体的最大成员来决定,所以如果在较大的结构体中有一个64位成员或其他东西,它可能会影响对齐前几名成员。对不起,我目前没有更可靠的资料或对此有更明确的解释。

在我自己的代码中,我宁愿直接将头文件嵌入到Frank Kreuger的回答中提到的较大结构中,并使用bigStruct.header.someMember类型的接口来避免任何和所有的铸造和对齐困难。

是的,你可以做到这一点。 SmallStructABC将采用与BigStructXYZ的第一部分完全相同的内存位置。

我用这与工会。系统收到一个有效载荷,它可能是头或头+数据。

我写了工会这样的:

union HeaderOrHeaderData 
{ 
    SmallStructABC header; 
    BigStructXYZ headerData; 
}; 

HeaderOrHeaderData* ptr = (HeaderOrHeaderData*) data_ptr; 

这种方法比直接铸造的优点是可-By缺陷结构的mistake-指针(实际上指向小结构),并使用它,因为它指向大结构。

如果你总是使用工会,你会三思。

我用几个编译器,操作系统和平台试过这个解决方案。它在任何时候都可以正常工作。