Consider the following sample program:
#include <stdio.h> struct base { int a, b; }; struct embedded { struct base base; int c, d; }; struct pointed { struct base* base; int c, d; }; static void base_print(struct base* x) { printf("a: %d, b: %d\n", x->a, x->b); } static void tobase_embedded(void* object) { base_print(object); // no cast needed, suitably converted into first member. } static void tobase_pointed(void* object) { struct base* x = *(struct base**) object; // need this cast? base_print(x); } int main(void) { struct embedded em = {{4, 2}}; struct pointed pt = {&em.base}; tobase_embedded(&em); tobase_pointed(&pt); return 0; }
Compiled with
$ gcc -std=c99 -O2 -Wall -Werror -pedantic -o main main.c
Expected Result:
$ ./main a: 4, b: 2 a: 4, b: 2
The C99 standard refers to the first member of the structure:
C99 6.7.2.1 (13): A pointer to a structure object appropriately transformed indicates its initial element ... and vice versa. As a structural object, there may be an unnamed addition, but not at the beginning.
In the example program, a pointer to a struct embedded converted to a pointer to a struct base (via void* ) without the need for an explicit cast.
What if instead the first member is a pointer to the base, as in struct pointed ? I'm not sure what the composition of tobase_pointed . No discarded garbage is printed, but no compilation warnings / errors. The correct values ββfor base.a and base.b will be printed with the cast, but this is not very important if undefined behavior exists.
Is translation to convert struct pointed to its first struct base* element correct?
c
Adam
source share