this is my struct :
struct Node {
struct Node* data;
struct Node* links[4];
}
assuming there is no padding, does Node->links[-1]
guaranteed to be pointing on Node::data
?
this is my struct :
struct Node {
struct Node* data;
struct Node* links[4];
}
assuming there is no padding, does Node->links[-1]
guaranteed to be pointing on Node::data
?
I'd say yes, but why then don't declare it as
struct Node {
struct Node* links[5];
}
No guarantee; this is undefined behaviour:
In practice, it's quite possible that you will end up pointing at data
, but any attempts to access it will result in UB.
A union
might help you here. Something like this:
struct Node {
union {
Node *data;
struct {
Node *lnk[5];
} links;
}
}
Yes, it almost certainly will point at data
, but it may not be precisely a guaranty.
You actually do get a guaranty that x[-1]
is the same thing as *(x - 1)
, so, depending on what you put at the address of x - 1
, then you do have a sort of guaranty. (And don't forget that when subtracting from pointers, the decrement is by the size of the item.)
Although others have objected on the basis of strict aliasing, in this case the types are the same so the elaborate optimizations should not remove your expected behavior.
This is implementation defined, depending on how the implementation pads structures and arrays. However, as long as it pads structs and arrays the same way, it should work.
Array subscripting is defined in terms of pointer arithmetic, and the C99 standard has this to say about pointer arithmetic:
If both the pointer operand and the result point to elements of the same array object, or one past the last element of the array object, the evaluation shall not produce an overflow; otherwise, the behavior is undefined.
So accessing Node->links[-1]
(even just getting the address of Node->links[-1]
) is undefined behavior, strictly speaking. So you have no guarantee that Node->links[-1]
will get you Node::data
.
But as many commentators mention, it will work pretty much always. I'd still consider it poor programming practice that should be avoided. If not for the technicality, then because it requires that modifications to struct Node
can easily cause bugs that the compiler will not help you with. When someone adds something between data
and links
, things will mysteriously break.