繁体   English   中英

当 (void *) p == (void *) *p - 标准对此有何评论?

[英]When (void *) p == (void *) *p - What does the Standard say about this?

例子:

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

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

通常,如果p是指向数组的指针,则p*p的对象表示(即位模式)是相等的。

我只是失去了,完全不能确定这种行为的便携性。

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

此比较保证为 1。

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

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

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

在您的特定情况下, p指向一个数组, *p是数组本身,并且在表达式中使用*p产生一个指向其第一个成员的指针。 两者都转换为void *以赋予它们一个通用类型。 因此,这种比较将始终评估为 1。

通常,如果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 *会产生一个指向对象第一个字节的指针,以及一个指向对象的第一个字节的指针。数组与其第一个元素的第一个字节相同。

暂无
暂无

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

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