typecasting bigger or smaller structure in C
I have two structures in C program: SmallStructABC and BigStructXYZ
I have several members in both of them; SmallStructABC's all 10 members are exactly same as first 10 members of BigStructXYZ. BigStructXYZ has 50 additional members.
Is it OK to type-cast this two structures to each other?
SmallStructABC *i = (BigStructXYZ*)j;
BigStructXYZ *a = (SmallStructABC*)b;
I only access first 10 (common) members after type-casting..
I wrote C program and its working fine on my machine. Just wanted to verify if I need to take care of any corner cases (alignment, invalid rea开发者_如何学运维d, non-gcc compilation etc)..
EDIT: Q: Why I want to do something like this?
A: BigStructXYZ is very big in size (say 50KB) and contains some header (keys, map etc). I compress this data before sending over network. I leave header (in our case its SmallStructABC) as it is. By doing type-cast, I can access these keys from header as and when required.
No, this is not a good idea. Much better would be to type cast pointers to the structures and manipulate them through the pointers:
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;
}
An alternative and safer design is to define Big
in terms of Small
:
typedef struct Small {
int foo;
};
typedef struct Big {
Small small;
int y;
};
The code above won't compile. Is j
already a BigStructXYZ, and did you mean to cast it to SmallStructABC?
Whatever the case, what you're trying to do is a bad idea. It would be better to have SmallStructXYZ as the first field inside BigStructXYZ and work thus:
SmallStructABC i = j.smallStruct;
BigStructXYZ a = { b };
I can think of cases where this wouldn't be guaranteed to work off the top of my head, but it should be fine on most platforms in most situations. One I'm thinking of off the top of my head is that alignment is supposed to be determined by the largest member of a struct, so if there was a 64 bit member or something else in the larger struct it could potentially affect the alignment of the first few members. I'm sorry that I don't have a more solid source or clearer explanation of this available at the moment.
In my own code I'd prefer to embed the header directly into the larger struct as mentioned in Frank Kreuger's answer and use a bigStruct.header.someMember
type of interface to avoid any and all casting and alignment difficulties.
Yes you can do it. SmallStructABC will take exactly the same location in memory as the first part of BigStructXYZ.
I used this with unions. The system receives a payload, it might be header or header+data.
I wrote union like this:
union HeaderOrHeaderData
{
SmallStructABC header;
BigStructXYZ headerData;
};
HeaderOrHeaderData* ptr = (HeaderOrHeaderData*) data_ptr;
The advantage of this method over direct casting is that may -by mistake- the pointer of bug struct (which actually point to small struct) and use it as it points to big struct.
If you always use the union, you will think twice.
I tried this solution with couple of compilers, operating systems and plateforms. It works fine at all times.
精彩评论