I have been looking into an un-traditional way of achieving struct "polymorphism" in pre-C11 C. Let's say we have 2 structs:
struct s1 {
int var1;
char var2;
long var3;
};
struct s2 {
int var1;
char var2;
long var3;
char var4;
int var5;
};
On most compilers, we could safely cast between pointers to the two and then access the common first members if no padding takes place. However, this is not standartized behaviour.
Now, I found the following line in the C standard as far as C89:
One special guarantee is made in order to simplify the use of unions: If a union contains several structures that share a common initial sequence, and if the union object currently contains one of these structures, it is permitted to inspect the common initial part of any of them. Two structures share a common initial sequence if corresponding members have compatible types for a sequence of one or more initial members.
It also states the following:
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.
Now, if I create a union of these two structs:
union s2_polymorphic {
struct s1 base;
struct s2 derived;
};
And use it this way:
union s2_polymorphic test_s2_polymorphic, *ptest_s2_polymorphic;
struct s2 *ptest_s2;
struct s1 *ptest_s1;
ptest_s2_polymorphic = &test_s2_polymorphic;
ptest_s2 = (struct s2*)ptest_s2_polymorphic;
ptest_s2->var1 = 1;
ptest_s2->var2 = '2';
ptest_s1 = (struct s1*)ptest_s2;
printf("ptest_s1->var1 = %d
", ptest_s1->var1);
printf("ptest_s1->var2 = %c
", ptest_s1->var2);
Which compiles and runs fine and gives, on gcc (GCC) 4.8.3 20140911, the output
ptest_s1->var1 = 1
ptest_s1->var2 = 2
Will the behaviour be well-defined, according to the quotes from the standard given above?
See Question&Answers more detail:
os