0

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

3
  • 1
    The behavior of comparing them with <, >, <=, 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.) Commented Mar 2, 2020 at 12:53
  • @EricPostpischil Yes, I did not account 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 [...] Commented Mar 2, 2020 at 12:59
  • Since ino_buf points to an array of 4096 structures of type struct inotify_event (with zero length name), you should be able to compare both first_event and second_event as 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. Commented Mar 2, 2020 at 18:14

1 Answer 1

1

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.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.