我有这个代码,我一直试图弄清楚指针,数组组合。
int main()
{
int s[4][2] = {
{1234,56},
{1212,13},
{1434,80},
{1312,78}
};
printf("%d\n",s[2]);
printf("%d\n",*s[2]);
printf("%d\n",s+2);
printf("%d\n",*(s+2));
return 0;
}
怀疑是: 即使s [2]和(s + 2)引用相同的地址,为什么*(s [2])打印该值(即1434)但*(s + 2)打印相同的地址(s +) 2)已打印。 Isn&#t; t *(s + 2)是第3个1D数组地址的平均值(即s [2] [0])?
答案 0 :(得分:6)
让我们看看你的数组在内存中的外观:
+---------+---------+---------+---------+---------+---------+---------+---------+ | s[0][0] | s[0][1] | s[1][0] | s[1][1] | s[2][0] | s[2][1] | s[3][0] | s[3][1] | +---------+---------+---------+---------+---------+---------+---------+---------+ ^ ^ ^ ^ | | | | &s[0][0] &s[0][1] &s[1][1] | | | | &s[0] &s[1] | | | | s[0] s[1] | | | | s s+1 | | | &s &s+1
现在让我们来s[0][0]
,您有五个可能指向该位置的指针:
&s[0][0]
。这是int *
类型。&s[0]
。这是int (*)[2]
类型。s[0]
。这将衰减为指向s[0]
中第一个元素的指针,并且等于1. s
。这将衰减为指向s
中第一个元素的指针,并且等于2. &s
。指向数组的指针,类型为int (*)[4][2]
。正如你所看到的,你可以有很多不同的指针指向同一个位置,但它们可能意味着不同的东西,这在语义上会产生很大的不同。
答案 1 :(得分:0)
s [2]和(s + 2)链接到您使用简单printf查看的相同地址。
然后你有一个未定义的行为,因为%d
指的是一个整数但s[2]
,s+2
和*(s+2)
是指针,你必须使用引用指针的%p
。
这是你的代码:
#include <stdio.h>
int main()
{
int s[4][2] = {
{1234,56},
{1212,13},
{1434,80},
{1312,78}
};
printf("%p\n",s[2]);
printf("%d\n",*s[2]);
printf("%p\n",s+2);
printf("%p\n",*(s+2));
return 0;
}
不,*(s+2)
并不意味着s[2][0]
它只是s的第二个元素的逻辑地址。您必须*(s[2])
使用s[2][0]
。
答案 2 :(得分:0)
除了数组名称之外,即使s [2]和(s + 2)引用相同的地址,为什么*(s [2])打印该值(即1434)但*(s + 2)打印相同的地址(s + 2)已打印。第3个数组的地址不是*(s + 2)的平均值(即s [2] [0])?
s
也是数组第一个元素的指针,它是第一行。
一般来说,请记住:
s[i][j]
相当于:
*(s[i] + j)
以及:
*(*(s + i) + j)
因此s[i]
相当于*(s+i)
和*(*(s+i) + 0)
。
基于这些,您可以看到:
s[2]
与*(s+2)
相同,表示数组的第三个元素。这是数组第三行的地址,与数组第三行第一行的地址完全相同。*(s[2])
表示*(*(s+2))
,表示数组第三个元素的 内容 。这是数组第三行的第一个元素的内容(即1434
)。如果您要打印s[2][0]
,则相当于*(*(s+2) + 0)
或*(*s[2])
。