简体   繁体   English

指向不同对象的指针的相等性比较

[英]Equality comparison of pointers to different objects

Inspired by this answering this question , I dug a little into the C11 and C99 standards for the use of equality operators on pointers (the original question concerns relational operators). 受此问题回答的启发,我对C11和C99标准进行了深入研究,以在指针上使用相等运算符(最初的问题涉及关系运算符)。 Here's what C11 has to say (C99 is similar) at §6.5.9.6: 以下是§6.5.9.6中C11所说的(C99类似):

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, both are pointers to one past the last element of the same array object, or one is a pointer to one past the end of one array object and the other is a pointer to the start of a different array object that happens to immediately follow the first array object in the address space. 当且仅当两个都是空指针时,两个指针比较相等,两个都是指向同一对象的指针(包括指向对象和它的开始处的子对象的指针)或函数,都是指向同一数组的最后一个元素的指针对象,或者一个是指向一个数组对象末尾的指针,另一个是指向另一个数组对象的起点的指针,该数组对象恰好紧随地址空间中的第一个数组对象。 94 ) 94

Footnote 94 says (and note that footnotes are non-normative): 脚注94说(并且请注意,脚注是非规范性的):

Two objects may be adjacent in memory because they are adjacent elements of a larger array or adjacent members of a structure with no padding between them, or because the implementation chose to place them so, even though they are unrelated. 两个对象可能在内存中相邻,这是因为它们是较大数组的相邻元素或结构的相邻成员之间没有填充,或者是由于实现方式选择放置它们,即使它们是不相关的。 If prior invalid pointer operations (such as accesses outside array bounds) produced undefined behavior, subsequent comparisons also produce undefined behavior. 如果先前的无效指针操作(例如,在数组范围之外进行访问)产生了未定义的行为,则后续的比较也将产生未定义的行为。

The body of the text and the non-normative note appear to be in conflict. 文本的正文和非规范性注释似乎存在冲突。 If one takes the 'if and only if' from the body of the text seriously, then in no other circumstances than those set out should equality be returned, and there is no room for UB. 如果人们认真对待案文中的“ if and only if” ,那么除规定的情况外,其他情况下均不得返回均等,UB也没有余地。 So, for instance this code: 因此,例如此代码:

uintptr_t a = 1;
uintptr_t b = 1;
void *ap = (void *)a;
void *bp = (void *)b;
printf ("%d\n", ap <= bp); /* UB by §6.5.8.5 */
printf ("%d\n", ap < bp);  /* UB by §6.5.8.5 */
printf ("%d\n", ap == bp); /* false by §6.5.9.6 ?? */

should print zero, as ap and bp are neither pointers to the same object or function, or any of the other bits set out. 应该打印零,因为apbp既不是指向同一对象或函数的指针,也不是列出的任何其他位。

In §6.5.8.5 (relational operators) the behaviour is more clear (my emphasis): 在第6.5.8.5节(关系运算符)中,行为更加清晰(我强调):

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 or incomplete 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 . 如果表达式P指向数组对象的元素,而表达式Q指向同一数组对象的最后一个元素,则指针表达式Q+1比较大于P In all other cases, the behavior is undefined. 在所有其他情况下,行为是不确定的。

Questions: 问题:

  • I am correct that there is some ambiguity as to when equality operators with pointers are permitted UB (comparing the footnote and the body of the text)? 我是正确的,关于何时允许使用带指针的相等运算符UB(比较脚注和正文)有一些歧义?

  • If there is no ambiguity, when precisely can comparison of pointers with equality operators be UB? 如果没有歧义,那么什么时候可以将指针与相等运算符进行比较精确到UB? For instance, is it always UB if at least one pointer is artificially created (per above)? 例如,如果至少人工创建了一个指针(是否按上),是否总是UB? What if one pointer refers to memory that has been free()d ? 如果一个指针指向已被free()d内存怎么办? Given the footnote is non-normative, can one conclude there is never UB, in the sense that all 'other' comparisons must yield false ? 给定脚注是非规范性的,就所有“其他”比较都必须得出false的意义而言,可以得出结论永远不会有UB吗?

  • Does §6.5.9.6 really mean that equality comparison of meaningless but bitwise equal pointers should always be false? §6.5.9.6真的意味着无意义但按位相等的指针的相等比较应始终为假吗?

Note this question is tagged ; 请注意,这个问题被标记为 I am not asking what in practice compilers do, as I believe already know the answer to that (compare them using the same technique as comparing integers). 我并不是在问编译器在做什么,因为我相信已经知道了答案(使用与比较整数相同的技术比较它们)。

Am I correct that there is some ambiguity as to when equality operators with pointers are UB? 我是否对带有指针的相等运算符何时为UB有一些含糊之处?

No, because this passage from §6.5.9(3): 不可以,因为第6.5.9(3)节的这段内容是:

The == and != operators are analogous to the relational operators except for their lower precedence. ==!=运算符类似于关系运算符,只是它们的优先级较低。

Implies that the following from §6.5.9(6) also applies to the equality operators: 暗示第6.5.9(6)节中的以下内容也适用于相等运算符:

When two pointers are compared [...] In all other cases, the behavior is undefined. 比较两个指针时,在所有其他情况下,行为均未定义。

If there is no ambiguity, when precisely can comparison of pointers with equality operators be UB? 如果没有歧义,那么什么时候可以将指针与相等运算符进行比较精确到UB?

There is undefined behaviour in all cases for which the standard does not explicitly define the behaviour. 在所有情况下,标准都没有明确定义行为,因此存在未定义的行为。

Is it always UB if at least one pointer is 如果至少一个指针是UB,是否总是UB artificially created 人为地创造 converted from an arbitrary integer? 从任意整数转换?

§6.3.2.3(5): §6.3.2.3(5):

An integer may be converted to any pointer type. 整数可以转换为任何指针类型。 Except as previously specified, the result is implementation-defined, might not be correctly aligned, might not point to an entity of the referenced type, and might be a trap representation. 除非先前指定,否则结果是实现定义的,可能未正确对齐,可能未指向引用类型的实体,并且可能是陷阱表示。

What if one pointer refers to memory that has been free d? 如果一个指针指向free内存该怎么办?

§6.2.4(2): §6.2.4(2):

The value of a pointer becomes indeterminate when the object it points to reaches the end of its lifetime. 当指针指向的对象达到其生命周期的尽头时,指针的值将变得不确定。

can one conclude there is never UB, in the sense that all 'other' comparisons must yield false? 在所有“其他”比较都必须得出错误的意义上,可以得出一个结论:永远不会存在UB吗?

No. The standard defines under what conditions two pointers must compare equal, and under what conditions two pointers must compare not equal. 否。该标准定义了在什么条件下两个指针必须比较相等,以及在什么条件下两个指针必须比较不相等。 Any equality comparisons between two pointers that falls outside both of those two sets of conditions invokes undefined behaviour. 两个指针都在这两个条件集之外的任何相等比较都会调用未定义的行为。

Does §6.5.9(6) really mean that equality comparison of meaningless but bitwise equal pointers should always be false? §6.5.9(6)真的意味着无意义但按位相等的指针的相等比较应始终为false吗?

No, it is undefined. 不,它是未定义的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM