指向不同对象的指针的相等性比较 [英] Equality comparison of pointers to different objects

查看:159
本文介绍了指向不同对象的指针的相等性比较的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

受此

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). Here's what C11 has to say (C99 is similar) at §6.5.9.6:

当且仅当两个都是空指针时,两个指针比较相等,两个都是指向同一个对象的指针(包括指向对象和它的开始处的子对象的指针)或函数,两者都是指向最后一个元素的指针 94 )

脚注94说(并且请注意脚注是非规范性的):

Footnote 94 says (and note that footnotes are non-normative):

两个对象可能在内存中相邻,这是因为它们是较大数组的相邻元素或结构的相邻成员之间没有填充,或者是由于实现方式选择放置它们,即使它们是不相关的.如果先前的无效指针操作(例如,在数组范围之外进行访问)产生了未定义的行为,则后续的比较也会产生未定义的行为.

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.

文本正文和非规范性注释似乎冲突.如果人们认真对待文本正文中的'if and only if',那么在没有其他条件的情况下,应返回相等性,并且没有UB的余地.因此,例如以下代码:

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. 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 ?? */

应打印零,因为apbp既不是指向同一对象或函数的指针,也不是其他列出的位.

should print zero, as ap and bp are neither pointers to the same object or function, or any of the other bits set out.

在§6.5.8.5(关系运算符)中,行为更加清晰(我强调):

In §6.5.8.5 (relational operators) the behaviour is more clear (my emphasis):

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

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. In all other cases, the behavior is undefined.

问题:

  • 我是正确的,关于何时允许带指针的相等运算符UB(比较脚注和文本正文)存在一些歧义?

  • 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?例如,如果至少人工创建了一个指针(是否按上面所述),是否总是UB?如果一个指针指向已经为free()d的内存怎么办?给定脚注是非规范性的,就所有其他"比较都必须产生false的意义上,可以得出一个结论:永远不会存在UB吗?

If there is no ambiguity, when precisely can comparison of pointers with equality operators be UB? For instance, is it always UB if at least one pointer is artificially created (per above)? What if one pointer refers to memory that has been 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?

第6.5.9.6节真的意味着无意义但按位相等的指针的相等比较应始终为假吗?

Does §6.5.9.6 really mean that equality comparison of meaningless but bitwise equal pointers should always be false?

请注意,该问题被标记为;我并不是在问编译器在做什么,因为我相信编译器已经知道了答案(使用与比较整数相同的技术比较它们).

Note this question is tagged language-lawyer; 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).

推荐答案

我正确地认为,带指针的相等运算符在UB上存在一些歧义吗?

否,因为这段来自6.5.9(3)节:

No, because this passage from §6.5.9(3):

==!=运算符与关系运算符类似,不同之处在于它们的优先级较低.

The == and != operators are analogous to the relational operators except for their lower precedence.

暗示第6.5.9(6)节中的以下内容也适用于相等运算符:

Implies that the following from §6.5.9(6) also applies to the equality operators:

比较两个指针[...]在所有其他情况下,该行为是不确定的.

When two pointers are compared [...] In all other cases, the behavior is undefined.

如果没有歧义,什么时候可以将指针与相等运算符进行比较?

在所有情况下,标准都没有明确定义行为,因此存在未定义的行为.

There is undefined behaviour in all cases for which the standard does not explicitly define the behaviour.

如果至少是一个人为创建的指针(至少是从任意整数转换而来的,则总是会UB)吗?

§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.

如果一个指针指向已经free d的内存怎么办?

What if one pointer refers to memory that has been freed?

§6.2.4(2):

当指针所指向的对象到达其生命周期的尽头时,指针的值将变得不确定.

The value of a pointer becomes indeterminate when the object it points to reaches the end of its lifetime.

可以得出结论,从某种意义上来说,所有其他"比较都必须得出假的结论吗?

不.该标准定义了在什么条件下两个指针必须比较相等,以及在什么条件下两个指针必须比较不相等.超出这两组条件中的两个条件的两个指针之间的任何相等比较都会调用未定义的行为.

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.

第6.5.9(6)条真的意味着无意义但按位相等的指针的相等比较应始终为假吗?

否,它是未定义的.

这篇关于指向不同对象的指针的相等性比较的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆