ВОПРОС: Законно ли сравнивать 2 указателя с гибкими элементами массива для более чем (меньше) и равенства?
Вот как объявляется struct inotify_event
в 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 */
};
Опуская проверки размера для простоты, давайте рассмотрим следующий код:
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?
//...
}
Я думаю, что сравнение указателей на структуру, содержащую гибкий член массива всегда UB (даже если они одинаковые)
N2346/6.7.2.1p3
(emp. mine):
последний элемент структуры с более чем одним именованным элементом может иметь неполный тип массива; такая структура (и любое объединение, содержащее, возможно, рекурсивно, член, который является такой структурой) не должно быть членом структуры или элементом массива .
OTOH, N2346/6.5.8p5
требуется, чтобы сравниваемые указатели принадлежали одному и тому же массиву:
Когда сравниваются два указателя, результат зависит от относительного расположения в адресном пространстве объекты, на которые указывают. Если два указателя на типы объектов оба указывают на один и тот же объект или оба указывают один за последним элементом одного и того же объекта массива, они сравниваются одинаково. Если указанные объекты являются членами одного и того же агрегатного объекта, указатели на элементы структуры, объявленные позже, сравниваются больше, чем указатели, на элементы, объявленные ранее в структуре, а указатели на элементы массива с большими значениями нижнего индекса сравниваются больше, чем указатели на элементы того же массива. с более низкими значениями индекса. Все указатели на члены одного и того же объекта объединения сравниваются одинаково. Если выражение P указывает на элемент объекта массива, а выражение Q указывает на последний элемент того же объекта массива, выражение указателя Q + 1 сравнивается больше, чем P. Во всех других случаях поведение не определено.
OTOOH, я обнаружил N2346/6.5.8p4
, противоречащим определению структур с гибкими элементами массива:
Для целей из этих операторов указатель на объект, который не является элементом массива, ведет себя так же, как указатель на первый элемент массива длиной один с типом объекта в качестве его типа элемента.
Это означает, что, поскольку struct inotify_event *first_event
никогда не является элементом массива, N2346/6.7.2.1p3
, поэтому его можно рассматривать как элемент массива длины один, что противоречит N2346/6.7.2.1p3