This line is overly complex
-
offset=(char *)&((struct c *)(&((struct a *) 0)->y)->j)-(char *)((struct a *)0);
-
The main problem is that you have not taken account of the fact that -> has a higher precedence than casting so
(struct c *)(&((struct a *) 0)->y)->j
is equivalent to
(struct c *)((&((struct a *) 0)->y)->j)
that this actually takes an object of type c and tries to treat it as a pointer you need
((struct c *)(&((struct a *) 0)->y))->j
This takes an object of type c, dereferences it to get a pointer to object of type c, unnecessarily casts it to a pointer to an onject of type c (since it already has this type) and the references it to access a member.
This is the same as accessing an integer variable like this
i.e. quite unnecessary
So get rid of the cast
(&((struct a *) 0)->y)->j
Get rid of the dereference (&) followed by reference (->) and the extra set of parenthises
((struct a *) 0)->y.j
No I know that you are trying to access x given a pointer to y so what you are looking for here is the address of y so that you can calculate the offest to x. y is an addressable object itself, there is no need to access j in it and if fact this only leaves room for later errors as the calculation would go wrong if someone later added a member to y before j. Since you are going to deference this expression you can drop the .j giving
((struct a *) 0)->y
Putting that back into the line gives
-
offset=(char *)&(((struct a *) 0)->y)-(char *)((struct a *)0);
-
So this is the answer right?
Wrong, this is doesn't address the biggest problem of all which is that since this references the NULL pointer ( ((struct a *) 0)->y ) the code causes undefined behaviour. You have no guarantee it will work and just because it works in 1 place does not mean it will work everywhere.
If you have to do this (it is nasty but sometimes necessary) then all in all you would be better off declaring a variable of type a and using that to perform your calculations on.