0

问题:将 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(雇员我的):

具有多个命名成员的结构的最后一个成员可能具有不完整的数组类型;这样的结构(以及可能递归地包含这样的结构的成员的任何联合) 不应是结构的成员或数组的元素

OTOH,N2346/6.5.8p5需要比较的指针属于同一个数组:

比较两个指针时,结果取决于所指向对象在地址空间中的相对位置。如果指向对象类型的两个指针都指向同一个对象,或者都指向同一个数组对象的最后一个元素,它们比较相等。如果指向的对象是同一个聚合对象的成员,则指向稍后声明的结构成员的指针比较大于指向结构中较早声明的成员的指针,并且指向具有较大下标值的数组元素的指针比较大于指向同一数组的元素的指针具有较低的下标值。所有指向同一个联合对象成员的指针比较相等。如果表达式 P 指向一个数组对象的一个​​元素,而表达式 Q 指向同一个数组对象的最后一个元素,指针表达式 Q+1 比较大于 P 。在所有其他情况下,行为是未定义的。

OTOOH,我发现N2346/6.5.8p4与具有灵活数组成员的结构的定义相矛盾:

出于这些运算符的目的,指向不是数组元素的对象的指针与指向长度为 1 且对象类型作为其元素类型的数组的第一个元素的指针的行为相同。

意思是因为struct inotify_event *first_event它永远不是数组的元素,N2346/6.7.2.1p3所以它可以被认为是长度为一的数组的元素,矛盾N2346/6.7.2.1p3

4

1 回答 1

1

如果T是一个包含灵活数组成员的结构,则不能声明形式的对象或类型T[intVal];这是一个编译时约束,如果程序试图声明这样一个数组,则要求编译器发出诊断。

标准的一个单独部分指定指向类型对象的指针的T行为与指向类型对象的指针一样T[1]。我认为在合理适用的情况下,我不打算将具有灵活数组成员的结构排除在该条款之外。尝试声明类型的对象或 typedefT[1]将违反约束,需要进行诊断,并且不可能有两个不匹配的类型指针T属于同一数组,但没有理由一个高质量的实现,不将指向同一类型对象的两个指针之间的关系比较T视为指向同一数组的同一元素的两个指针之间的比较。

于 2020-03-04T17:59:13.740 回答