[英]Pointer vs Array in function definition: what is the difference between void fct1(int *p) and void fct1(int 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.