The C99 standard states that:
When two pointers are subtracted, both shall point to elements of the same array object, or one past the last element of the array object
Consider the following code:
struct test {
int x[5];
char something;
short y[5];
};
...
struct test s = { ... };
char *p = (char *) s.x;
char *q = (char *) s.y;
printf("%td\n", q - p);
This obviously breaks the above rule, since the p
and q
pointers are pointing to different "array objects", and, according to the rule, the q - p
difference is undefined.
But in practice, why should such a thing ever result in undefined behaviour? After all, the struct members are laid out sequentially (just as array elements are), with any potential padding between the members. True, the amount of padding will vary across implementations and that would affect the outcome of the calculations, but why should that result be "undefined"?
My question is, can we suppose that the standard is just "ignorant" of this issue, or is there a good reason for not broadening this rule? Couldn't the above rule be rephrased to "both shall point to elements of the same array object or members of the same struct"?
My only suspicion are segmented memory architectures where the members might end up in different segments. Is that the case?
I also suspect that this is the reason why GCC defines its own __builtin_offsetof
, in order to have a "standards compliant" definition of the offsetof
macro.
EDIT:
As already pointed out, arithmetic on void pointers is not allowed by the standard. It is a GNU extension that fires a warning only when GCC is passed -std=c99 -pedantic
. I'm replacing the void *
pointers with char *
pointers.
char *
then. – Amesvoid*
by treatingsizeof(void)
as 1 (same as achar*
). So for the purposes of your question, it makes no difference. – Satiablestruct {int x, y;} foo;
, if for some integer valuen
, the address offoo.y
would equal((int*)&foo)+n
, then&foo.x
and&foo.y
would be the addresses of elements 0 andn
of an array of integers that starts at address&foo
. Unfortunately, the authors of the Standard ham-fistedly threw in aliasing rules that depend upon details of "objects" which they never defined because the language had no need for them. – Vogue