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
<,>,<=, or>=is not defined by the C standard. Comparing them with==or!=works in the usual way. (This is undoubtedly the intent of the C standard, regardless of any quibbles about wording and whether or not it may be treated as an array of length one.)6.5.9p6: Two pointers compare equal if and only if both are null pointers, both are pointers to the same object (including a pointer to an object and a subobject at its beginning) or function [...]ino_bufpoints to an array of 4096 structures of typestruct inotify_event(with zero lengthname), you should be able to compare bothfirst_eventandsecond_eventas long as they point into or just behind that array. BUT, because you offset the second pointer, it will mostly be not aligned. -- I think the emphasized part of 6.7.2.1p3 refers to not being able to determine the size of such a structure at compile time.