【问题标题】:When (void *) p == (void *) *p - What does the Standard say about this?When (void *) p == (void *) *p - 标准对此有何评论?
【发布时间】:2021-10-05 02:58:27
【问题描述】:

例子:

int a[99];
int (*p)[99] = &a;

// this prints 1
printf("%d\n", (void *) p == (void *) *p);

一般来说,如果p 是一个指向数组的指针,那么p*p 的对象表示(即位模式)都是相等的。

我只是迷路了,完全不确定这种行为的可移植性。

所以,我很好奇标准是否保证了这种行为。如果是这样,有人可以引用所有保证它的相关段落吗?

【问题讨论】:

  • p 指向整个数组,而*p 指向数组的第一个元素。但是这些恰好共享相同的地址。同样,指向结构的指针和指向结构第一个成员的指针也将共享相同的地址。

标签: arrays c pointers language-lawyer standards


【解决方案1】:

此比较保证为 1。

C standard 的相关部分是第 6.5.9p6 节关于相等运算符和指针比较:

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

请特别注意粗体字的段落。这意味着两件事:1)指向结构的指针和指向其第一个成员(适当转换的)的指针将比较相等,2)指向数组的指针和指向其第一个成员的指针(同样,适当的转换)将比较相等。

在您的特定情况下,p 指向一个数组,*p 是数组本身,在表达式中使用*p 会产生一个指向其第一个成员的指针。两者都转换为void * 以赋予它们一个通用类型。所以这个比较的结果总是 1。

【讨论】:

  • 这个论点有问题;虽然很难说到底是什么。对于其中一个历史平台,如果您尝试使用 char *char ** 进行此参数,它们将不会是位等价的,因为 char * 具有与所有其他指针类型不同的机器表示。它们比较相等只是因为类型转换会转换位。
  • @Joshua 我认为它们不一定要等价。 void * 能够保存任何对象指针,因此转换过程应该能够解决这个问题。没有什么说两个指针需要位等价才能相等。在浮点世界中,+0 和 -0 具有不同的 IEEE754 表示,但比较相等。
【解决方案2】:

一般来说,如果p 是一个指向数组的指针,那么p*p 的对象表示(即位模式)都是相等的。

如果p 是指向数组的指针,那么*p 就是数组。数组的位表示是数组元素的位表示的串联(因为 C 2018 6.2.5 20 表示数组由连续分配的对象组成)。数组中的位通常不等于指针中的位。

但是,当数组在表达式中用作一元 & 的操作数或 sizeof 的操作数或用作用于初始化数组的字符串文字时,该数组将自动转换为指向它的第一个元素。数组*p的第一个元素是(*p)[0],所以*p会自动转换为&(*p)[0]

那么问题是(void *) p是否等于(void *) &(*p)[0]

C 2018 6.3.2.3 1 告诉我们任何指向对象类型的指针都可以转换为void *。但是,当指针为void * 时,它并没有告诉我们比较的结果是什么。它确实告诉我们,将void * 转换回其原始类型会产生一个与原始类型比较相等的指针。

C 2018 6.5.9 6 告诉我们“两个指针比较相等当且仅当……,两者都是指向同一个对象的指针(包括指向对象的指针和开头的子对象)……”(我省略了其他一些这里不关心的情况。)给定两个void *,我们该怎么做?似乎意图是指向“指向对象”的指针,即使它当前采用void * 的形式。然后(void *) p 指向数组,(void *) &(*p)[0] 指向其开头的子对象,因此它们比较相等。

(char *) p == (char *) *p 的语义会更清晰,因为 C 2018 6.3.2.3 7 告诉我们转换为 char * 会产生指向对象第一个字节的指针,并且数组的第一个字节与第一个元素的第一个字节。

【讨论】:

  • 哦,对了。我完全不小心。我自己知道转换规则。我将在上面的问题中插入一个编辑。
猜你喜欢
  • 2011-05-30
  • 2021-04-06
  • 2014-05-26
  • 2014-09-12
  • 2013-10-19
  • 2023-03-30
  • 2023-04-11
  • 2011-08-31
相关资源
最近更新 更多