指向不同对象的指针的等式比较

时间:2016-11-26 18:22:04

标签: c language-lawyer

受此answering this question的启发,我在C11和C99标准中挖了一些关于在指针上使用相等运算符的标准(原始问题涉及关系运算符)。这是C11在§6.5.9.6中所说的(C99类似):

  

两个指针比较相等,当且仅当两个都是空指针时,两者都是指向同一对象的指针(包括指向对象的指针和在其开头的子对象)或函数,两者都指向超过最后一个元素的指针。相同的数组对象,或者一个是指向一个数组对象末尾的指针,另一个是指向不同数组对象的开头的指针,该数组对象恰好跟随地址空间中的第一个数组对象。 94

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

  

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

案文正文和非规范性说明似乎存在冲突。如果一个人认真地使用',当且仅当'来自文本正文时,那么除了那些之外的其他情况都不应该返回相等,并且UB没有空间。所以,例如这段代码:

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既不是指向同一对象或函数的指针,也不是指定的任何其他位。

在§6.5.8.5(关系运算符)中,行为更清晰(我的重点):

  

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

问题:

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

  • 如果没有歧义,那么精确可以比较具有相等运算符的指针是否为UB?例如,如果至少有一个指针被人为地创建(如上所述),它总是UB吗?如果一个指针指的是P的内存怎么办?鉴于脚注是非规范性的,可以得出结论,从来没有UB,因为所有“其他”比较必须产生free()d吗?

  • §6.5.9.6是否真的意味着无意义但按位相等的指针的相等比较应该总是假的?

请注意,此问题已标记为;我不是在问实际编译器在做什么,因为我相信已经知道答案(使用与比较整数相同的技术进行比较)。

1 个答案:

答案 0 :(得分:-1)

我是否正确指出有指针的相等运算符是否为UB时存在一些歧义?

不,因为这段来自§6.5.9(3):

  

library(RSelenium) url="http://stackoverflow.com/search?q=r+program" remdir<-remoteDriver(remoteServerAddr = "localhost", port = 4444, browserName = "firefox") remdir$open() remdir$navigate(url) fun.XpathExtractText<-function(xp, remdir) { cat("\ncheck if session open\n") #look in env for an open session if (is.na(remdir$sessionid)) stop("ERROR NO SESSION ID open new one") cat("session found\n") #accept xpath expression as is cat("calling\n") tgt <- remdir$findElements(using = "xpath",as.character(xp)) cat("Target locked\n") txt<-lapply(tgt,function(c){c$getElementText()}) return(txt) } ==运算符类似于关系运算符,除了它们的优先级较低。

意味着§6.5.9(6)中的以下内容也适用于相等运算符:

  

比较两个指针[...]在所有其他情况下,行为未定义。

如果没有歧义,何时可以将具有相等运算符的指针精确地比作UB?

在标准未明确定义行为的所有情况下都存在未定义的行为。

如果至少有一个指针从任意整数转换为人工创建,它总是UB吗?

§6.3.2.3(5):

  

整数可以转换为任何指针类型。除非先前指定,否则结果是实现定义的,可能未正确对齐,可能不指向引用类型的实体,并且可能是陷阱表示。

如果一个指针指的是!= d的内存怎么办?

第6.2.4节(2):

  

当指针指向的对象到达其生命周期的末尾时,指针的值变得不确定。

可以得出结论,从来没有UB,因为所有“其他”比较都必须产生错误吗?

没有。标准定义了两个指针在什么条件下必须比较相等,并且在什么条件下两个指针必须比较不相等。在这两组条件之外的两个指针之间的任何相等比较都会调用未定义的行为。

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

不,它未定义。