这是源代码
int main()
{
int s[4][2]={
{1,2},
{3,4},
{5,6},
{7,8},
};
printf("%d\n",*(s+2);
return 0;
}
上述代码打印s [2]或(s + 2)数组的基地址,即元素5的地址 但为什么它不打印价值 5
答案 0 :(得分:4)
s
是指向数组s
的第一个元素(在衰减之后)的指针,即数组s
的第一行。它是int (*)[2]
类型,即指向2
元素数组的指针。 s=2
是指向数组s
的第3行的指针。
另一方面,*s
的类型为int [2]
,即2
int
的raay,这是因为*
正在取消引用指针表达式s
(衰减到指向第一行的指针),这会导致2
int的数组。由于8s
也是一个数组,它将衰减到指向其第一个元素的指针,即s[0][0]
。
现在*(s+2)
取消引用数组s
的第3行。它还会提供一系列2
int
s。此外,它将衰减到指向其第一个元素的指针,即s[0][2]
因此,在上面的讨论之后,你可以说s
是一个指向所有衰减执行后指针的指针(不完全正确)。
取消引用指向int
的指针的指针(在衰减后)将为您提供指向int
的指针。您需要再次derefernce *(s+2)
来获取它指向的值。
printf("%d\n",*(*(s+2));
注: s
,*s
,&s
,&s[0]
,&s[0][0]
都指向同一位置,但全部属于不同类型的。
(s+2)
是指向数组s
的第3行的指针。它会给你第3行的起始地址。 *(s+2)
是指向第3行第一个元素的指针,即它将为您提供元素s[0][2]
的地址。虽然这两者在打印时给你的位置值相同但两者都有不同的类型。
答案 1 :(得分:1)
*(s+2)
指向“子阵列”{5,6}
,其第一个元素是5
:
*(s+0) ---> {1,2},
*(s+1) ---> {3,4},
*(s+2) ---> {5,6},
*(s+3) ---> {7,8}
因此,要从指针中获取值指向,您必须再插入另一个“*
”到 deference 指针。这应该有效:
/* Dereference s+2 two times, to get the value 5: */
printf("%d\n",*(*(s+2)));
你可以这样想。
*(s+2)
是指向子数组{5,6}
的指针。
引入一个新的中间变量int * a
,等于*(s+2)
。
现在a
是指向数组{5,6}
的(简单的,单级别的间接)指针,实际上是指该数组的第一个元素。
如果你想要值5
,你必须使用*a
取消引用指针(就像你对普通指针和一维数组所做的那样)。 / p>
现在,如果您将a
替换为*(s+2)
,*a
将变为*(*(s+2))
(来自s
的双重引用)。
答案 2 :(得分:1)
在大多数情况下,请记住,调用数组的名称会返回数组的第一个元素的地址,也称为数组的基址,例如
int arr={0,1,2,3};
int *p=arr
在此代码中,指针p
具有arr
的第一个元素的地址,其类型为int *。
现在让我们一步一步地实现*(s+2)
返回的内容,首先调用数组的名称s
返回数组的第一个元素的地址,以防万一也是类型{ {1}},因此返回的地址将是int [2]
类型,现在向此地址添加2将通过简单的指针算法累加给出数组的第3个元素的地址,并且在取消引用地址后得到{{} 1}},你显然无法打印数组。
并且还值得知道编译器通过指针算术访问所有数组,因此在int (*)[2]
int [2] array
元素中s[4][2]
访问[3][0]
,您可以使用相同的方式访问任何元素。
如果你想通过*(*(s+2)+0)
引用第3个元素,你可以(s+2)
,你可以明确地转换*((int *)s+2)
返回的地址,实际上是s
类型的地址int (*)[2]
。你不必要地使用演员表并不是一个好主意,它可能导致不必要的复杂化。
使用指针时要小心,并始终专注于事先使用它所指的地址类型。
答案 3 :(得分:0)
此处s
是指向指针的指针,因此您可以期望*(s+2)
打印指针。
尝试此操作以获取5
:*(*(s+2))
答案 4 :(得分:0)
s
是int**
,指向int的指针。
*(s+2)
是int*
,指向int的指针。
*(*(s+2))
或**(s+2)
是您要找的int
。
如果您想访问6
,则需要*(*(s+2)+1)
。