我正在学习C中数组中的指针。我真的很困惑指针数组是什么。看看这个例子 -
#include<stdio.h>
int main()
{
static int a[] = { 0, 1, 2, 3, 4 };
int *p[] = { a, a+1, a+2, a+3, a+4 };
printf( "%p %p %p %d ", p, *p, a, *(*p));
return 0;
}
当我运行此程序时,我会为a
和p
获取不同的地址。为什么?据我所知,a
是指向数组的第0个元素的指针,p
是指向指针的指针。 a
指向第0个元素的地址,但是p
呢?有地址的地址吗?
答案 0 :(得分:1)
地址由位组成,任何由位组成的地址都可以放入存储器中。记忆中的一切都有一个地址。
这并不意味着程序中的每个地址值都在内存中。地址也可以是用作表达式一部分的临时值。
同样适用于整数值。其中一些是在记忆中,一些不是。你可以这样:
int i = 7;
int *p = &i;
但你不能这样做:
int *q = &7;
i
是内存中存在的变量的名称,您可以使用&
获取其地址。值7存储在该地址。 &7
无法正常工作,因为程序源代码中存在文字7
并不足以导致值7在运行时存在于内存中。
稍微提一点技术术语,i
是左值,7
是右值。前缀&
运算符要求其操作数为左值,但它不会产生左值结果。 &i
是一个右值,就像7
一样。这就是&(&i)
无效的原因。
答案 1 :(得分:1)
将变量视为地址的别名。当你有
int v1 = 10;
v1
是包含10
的地址的别名。
当你有:
int* v2 = &v1;
v2
是包含v1
地址的地址的别名。
地址可以包含可以是其他地址或原始值的值,例如int
s,char
s等。
要回答你的问题,
有地址的地址吗?
严格来说,答案是否定的。但如果你有:
int** v3 = &v2;
然后,v3
是地址的别名,地址的值为地址的值,其地址值为int
。
在你的情况下,
static int a[] = { 0, 1, 2, 3, 4 };
int *p[] = { a, a+1, a+2, a+3, a+4 };
a
是一个数组,是int
的数组。在表达式中使用时,它会衰减为指针。 a
,a+1
等评估指向int
s。
p
也是一个数组,int*
的数组。在表达式中使用时,它会衰减为指针。 p
,p+1
等评估指向int*
s。
p
评估为包含int*
- a
的地址
a
评估的地址包含int
- 0
。
*p
评估为a
*a
评估为0
。
答案 2 :(得分:1)
C中没有两个变量可能具有相同的地址。
数组a
和数组p
是变量。所以他们必须有不同的地址。
这是另一个例子:
int x[3] = { 0, 1, 2 } ;
int y[3] = { 0, 1, 2 };
printf("%p %p\n", &x , &y);
示例中的数组存储的数据类型与int
不同,这没有区别。
此外,数组的第一个元素始终位于数组的开头,因此输出x
(当您尝试打印其值时衰减为&x[0]
)将获得与&x
。
答案 3 :(得分:0)
p 指向内存块的第一个位置,包含:
{ a,a+1,a+2,a+3,a+4 }
a 指向包含
的内存块的第一个位置{0,1,2,3,4}
这两个因此指向不同的内存块。
p [0] (或 * p )和 a 应具有相同的地址。
答案 4 :(得分:0)
想想事情在记忆中的组织:
a:包含5个整数到0到4的连续内存区域 - a是一个数组而&a
== &(a[0])
(并且与a
相同)
p是一个指向int的指针数组:它又是一个包含5个指针的连续内存区域。 p是一个数组,因此p == &(p[0])
。但现在p[0]
是一个包含地址a
的指针。
所以p
是包含a
地址的内存区域的地址:它实际上是地址的地址
当然,*p
(或p[0]
)与a
相同,**p
为a[0]
。但至于任何数组p
不与p[0]
相同