When doing pointer arithmetic with offsetof
, is it well defined behavior to take the address of a struct, add the offset of a member to it, and then dereference that address to get to the underlying member?
Consider the following example:
#include <stddef.h>
#include <stdio.h>
typedef struct {
const char* a;
const char* b;
} A;
int main() {
A test[3] = {
{.a = "Hello", .b = "there."},
{.a = "How are", .b = "you?"},
{.a = "I\'m", .b = "fine."}};
for (size_t i = 0; i < 3; ++i) {
char* ptr = (char*) &test[i];
ptr += offsetof(A, b);
printf("%s\n", *(char**)ptr);
}
}
This should print "there.", "you?" and "fine." on three consecutive lines, which it currently does with both clang and gcc, as you can verify yourself on wandbox. However, I am unsure whether any of these pointer casts and arithmetic violate some rule which would cause the behavior to become undefined.
offsetof
use. – Godesbergtest[i].b
will do the same pointer arithmetic as necessary, but is guaranteed to be correct behavior while pointer hacks are not. And since it's the common case, it's the one that compiler designers would focus optimization on, whereas they might not have as effectively optimized pointer hacks. One could imagine a case wheretest[i].b
is compiled to a singleload
instruction while the manual arithmetic is done as individual steps followed by aload
. – Thralldomoffsetof
or a compiler that actually processes the Common Initial Sequence guarantees in usable fashion. – Mclaughlin