2

我有一个类型化的指针,typed它是使用指针算法初始化的,以指向数组中的一个对象。我还有一个函数,它需要两个指针参数,第一个类型与上述指针相同,第二个是void *(参见myfunc()下面的代码)。

typed如果我作为第一个参数传递,另一个指针类型typed与第二个参数相同,然后在函数内比较它们是否相等,那是未定义的行为吗?

#include <stdio.h>

typedef struct S {int i; float f;} s;

void myfunc(s * a, void * b)
{
  if (a == b)  // <-------------------------------- is this UB?
    printf("the same\n");
}

int main()
{
  s myarray[] = {{7, 7.0}, {3, 3.0}};
  s * typed = myarray + 1;
  myfunc(typed, &(myarray[0]));

  return 0;
}

更新:好的,所以我在上面发布我的问题后一天回来,有两个很好的答案(感谢@SouravGhosh 和@dbush)。一个比另一个早了不到一分钟(!),但从第一个评论的外观来看,答案最初是错误的,只有在第二个答案发布后才更正。我接受哪一个?在这种情况下,是否有一种协议可以接受一个答案而不是另一个答案?

4

2 回答 2

4

不,这不是未定义的行为。这是在等式运算符约束的规范中允许并明确定义的。引用C11,第 6.5.9 章

一个操作数是指向对象类型的指针,另一个是指向 void 的限定或非限定版本的指针;

以及同一章的第 5 段

[...] 如果一个操作数是指向对象类型的指针,而另一个是指向 void 的限定或非限定版本的指针,则前者将转换为后者的类型。

于 2020-07-29T15:38:20.077 回答
3

这种比较是明确定义的。

当 avoid *通过 与另一个指针类型进行比较时,另一个指针==将转换为void *

此外, C 标准的第 6.5.9p6 节对与 的指针比较进行了以下说明==

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

这里没有提到未定义的行为。

于 2020-07-29T15:37:28.767 回答