Pointer Compatibility

Suppose we have two structures:

typedef struct Struct1 { short a_short; int id; } Struct1; typedef struct Struct2 { short a_short; int id; short another_short; } Struct2; 

Is it safe to distinguish from Struct2 * to Struct1 * ? What does ANSI spec say about this? I know that some compilers have the ability to reorder structural fields to optimize memory usage, which can lead to incompatibility between the two structures. Is there a way to make sure this code is valid regardless of the compiler flag?

Thanks!

+7
source share
4 answers

Struct pointer types always have the same representation in C.

(C99, 6.2.5p27) "All pointers to structure types must have the same representation and alignment as each other."

And members in structure types are always in order in C.

(C99, 6.7.2.1p5) "a structure is a type consisting of a sequence of members whose storage is distributed in an ordered sequence"

+5
source

As far as I know, this is safe.

But it is much better, if possible, to do:

 typedef struct { Struct1 struct1; short another_short; } Struct2; 

Then you even told the compiler that Struct2 starts with an instance of Struct1 , and since the pointer to the structure always points to its first member, you can treat Struct2 * as Struct1 * .

+3
source

Most likely it will work. But you ask very correctly how you can be sure that this code will be valid. So: somewhere in your program (possibly at startup) insert a bunch of ASSERT statements that make sure offsetof( Struct1.a_short ) is equal to offsetof( Struct2.a_short ) , etc. In addition, some programmer, besides you, may one day change one of these structures, but not the other, this is better than sorry.

+2
source

Yes, it is normal!

An example program is as follows.

 #include <stdio.h> typedef struct Struct1 { short a_short; int id; } Struct1; typedef struct Struct2 { short a_short; int id; short another_short; } Struct2; int main(void) { Struct2 s2 = {1, 2, 3}; Struct1 *ptr = &s2; void *vp = &s2; Struct1 *s1ptr = (Struct1 *)vp; printf("%d, %d \n", ptr->a_short, ptr->id); printf("%d, %d \n", s1ptr->a_short, s1ptr->id); return 0; } 
+1
source

All Articles