QUESTION: Is it legitimate to compare 2 pointers with flexible array members for more then (less then) and equality?
Here is how the struct inotify_event
is declared in Linux:
struct inotify_event {
int wd; /* Watch descriptor */
uint32_t mask; /* Mask describing event */
uint32_t cookie; /* Unique cookie associating related
events (for rename(2)) */
uint32_t len; /* Size of name field */
char name[]; /* Optional null-terminated name */
};
Omitting size checks for simplicity, let's consider the following code:
int inotify_fd = inotify_init();
//...
struct inotify_event *ino_buf = malloc(sizeof(inotify_event) * 4096);
read(inotify_fd, ino_buf, sizeof(inotify_event) * 4096));
struct inotify_event *first_event = ino_buf;
struct inotify_event *second_event =
((char *) ino_buf) + sizeof(struct inotify_event) + first_event->len;
if(first_event < second_event){ //UB?
//...
}
I think the comparison of pointers to structure containing flexible array member is always UB (even though they are the same)
N2346/6.7.2.1p3
(emp. mine):
the last member of a structure with more than one named member may have incomplete array type; such a structure (and any union containing, possibly recursively, a member that is such a structure) shall not be a member of a structure or an element of an array.
OTOH, N2346/6.5.8p5
required pointers being compared to belong to the same array:
When two pointers are compared, the result depends on the relative locations in the address space of the objects pointed to. If two pointers to object types both point to the same object, or both point one past the last element of the same array object, they compare equal. If the objects pointed to are members of the same aggregate object, pointers to structure members declared later compare greater than pointers to members declared earlier in the structure, and pointers to array elements with larger subscript values compare greater than pointers to elements of the same array with lower subscript values. All pointers to members of the same union object compare equal. If the expression P points to an element of an array object and the expression Q points to the last element of the same array object, the pointer expression Q+1 compares greater than P . In all other cases, the behavior is undefined.
OTOOH, I found the N2346/6.5.8p4
contradicting to the definition of structs with flexible array members:
For the purposes of these operators, a pointer to an object that is not an element of an array behaves the same as a pointer to the first element of an array of length one with the type of the object as its element type.
Meaning that since struct inotify_event *first_event
is never an element of an array by N2346/6.7.2.1p3
so it can be considered as an element of an array of length one, contradicting N2346/6.7.2.1p3
If T
is a structure that contains a flexible array member, one may not declare objects or types of the form T[intVal]
; that is a compile-time constraint, requiring that compilers issue a diagnostic if a program attempts to declare such an array.
A separate section of the Standard specifies that a pointer to object of type T
will behave as would a pointer to an object of type T[1]
. I don't think there's any intention to exclude structures with flexible array members from that provision in cases where it would sensibly apply. An attempt to declare an object or typedef of type T[1]
would be a constraint violation requiring a diagnostic, and it wouldn't be possible to have two non-matching pointers of type T
that were part of the same array, but there would be no reason for a quality implementation not to treat a relational comparison between two pointers to the same object of type T
as they would a comparison between two pointers to the same element of the same array.