Let's suppose I have a struct and extract the offset to a member:
struct A {
int x;
};
size_t xoff = offsetof(A, x);
how can I, given a pointer to struct A
extract the member in a standard conforming way? Assuming of course that we have a correct struct A*
and a correct offset. One attempt would be to do something like:
int getint(struct A* base, size_t off) {
return *(int*)((char*)base + off);
}
Which probably will work, but note for example that pointer arithmetics only seem to be defined in the standard if the pointers are pointers of the same array (or one past the end), this need not be the case. So technically that construct would seem to rely on undefined behaviour.
Another approach would be
int getint(struct A* base, size_t off) {
return *(int*)((uintptr_t)base + off);
}
which also probably would work, but note that intptr_t
is not required to exist and as far as I know arithmetics on intptr_t
doesn't need to yield the correct result (for example I recall some CPU has the capability to handle non-byte aligned addresses which would suggest that intptr_t
increases in steps of 8 for each char
in an array).
It looks like there's something forgotten in the standard (or something I've missed).
char*
and pointers that point into the same object (not necessarily array) are both valid. Waiting for an authoritative answer though. – Crayton(char *)base
can be used to move around anywhere withinbase
(and one past the end). Any object behaves like an array of size 1. – Jackquelinejackrabbitreturn *(int*)((char*)base + off);
can readily fail asint
access may be unaligned. E.g.int
access can cause bus fault on odd address. OTOH OP did say "Assuming ... we have a correct struct A* and a correct offset" – Mmeunsigned char
(No traps, no padding). – MmeA->x
to access the field. What do you what to do thatA->x
does not provide? If all code has isA
and the offset to fieldx
, lack of the field type/size prevents accessing in a conforming manner. – Mme