C 不理解*p[3]和(*p)[3]之间的区别

C 不理解*p[3]和(*p)[3]之间的区别,c,pointers,C,Pointers,在我的书中,有人写到,*p[3]将p声明为3个指针的数组。我得到了它。但是对于(*p)[3],有人写道,(*p)[3]将p声明为指向三个元素的数组的指针。这是什么意思?(*p)[3]没有例子。有人能给我举个例子吗 int a[3] = {1,2,3}; int (*p)[3]; p=&a; printf("%d %d %d",(*p)[0],(*p)[1],(*p)[2]); 首先,您必须了解a和&a之间的区别值将相同。但是它们的含义有很大的不同。这里a表示数组的第一个元素,

在我的书中,有人写到,
*p[3]将p声明为3个指针的数组。我得到了它。但是对于(*p)[3],有人写道,
(*p)[3]将p声明为指向三个元素的数组的指针。这是什么意思?(*p)[3]没有例子。有人能给我举个例子吗

int a[3] = {1,2,3};
int (*p)[3];
p=&a;    
printf("%d %d %d",(*p)[0],(*p)[1],(*p)[2]); 
首先,您必须了解a和&a之间的区别<a和&a的代码>值将相同。但是它们的含义有很大的不同。这里
a
表示
数组的
第一个元素
,即
&a[0]
&a
表示整个或
完整数组
。如果执行
a+1
,您将在
数组中找到下一个元素的地址,即
&a[1]
,但如果执行
&a+1
,它将
下一个地址
提供给
完整数组
,即此处
&a+1
=
&a[2]+1
。因此,这里的
p=&a
表示您已将
大小为3的数组的
地址分配给
指针p
类似的东西

int a[3]; // int array of size 3
int (*p)[3]; // pointer to int array of size 3

p = &a; // Make p point to the address of a
a
是一个
数组,大小为3
,可以包含三个元素。
p
被声明为
指针
,它应指向大小为3的
整数数组

int a;
int *p;
a
是一个整数。
p
是指向一个整数的指针,而不是一个整数数组,一个简单的整数

简化:将指针视为变量,它的值只是指向其他变量的地址。您可以指定指针可能指向的变量类型,在本例中,是一个大小为3的int数组。

基本上:

int *p[3]; // to access a value you need to do
           // *p[1] (take first entry and dereference it)
-------------------------
| first pointer to int  | <- p points here
-------------------------
| second pointer to int |
-------------------------
| third pointer to int  |
-------------------------

int (*p)[3] // to access a value you need to do
            // (*p)[1] (dereference pointer to array and take first value in array)
------------------  \
| first integer  |  |
------------------  |
| second integer |  } p points to the whole array
------------------  |
| third integer  |  |
------------------  /
int*p[3];//要访问值,您需要执行以下操作
//*p[1](取第一个条目并取消引用)
-------------------------
|第一个指向int的指针|例如
*p[3]
: 写这一切有点有趣。我希望这也有助于更好地理解

http://stackoverflow.com/questions/1810083/c-pointers-pointing-to-an-array-of-fixed-size

上面的链接可能会帮助您更好地理解这个概念。

这里有一个指向数组指针的例子;将多维数组作为函数参数传递

除非它是
sizeof
或一元
&
运算符的操作数,或者是用于初始化声明中另一个数组的字符串文字,否则“T
的N元素数组”类型的表达式将转换(“衰减”)为“指向
T
的指针”类型的表达式,表达式的值将是数组第一个元素的地址

因此,假设以下代码:

int foo[5][5];
bar( foo );
调用
bar
中的表达式
foo
的类型为“int
的5元素数组的5元素数组”;由于
foo
不是
sizeof
或一元
&
运算符的操作数,它将被转换为“指向
int
的5元素数组的指针”或
int(*)[5]
(在这种情况下,
t
==“int
的5元素数组”)类型的表达式
bar
的定义必须如下所示

void bar ( int (*arr)[5] ) { ... }
参数
arr
的类型为“指向
int
的5元素数组的指针”。
*arr
周围的括号是必需的,因为
[]
下标运算符的优先级高于一元
*
运算符,因此像
*p[i]
这样的表达式被解析为
*(p[i])
;取消引用下标操作的结果。要强制取消引用发生在下标之前,需要使用标识符显式地将一元
*
运算符分组:
(*p)[i]

在函数参数声明的上下文中,
ta[]
ta[N]
被视为
ta*a
;所有三个都将
a
声明为指向
T
的指针。因此,您可以将函数定义编写为

void bar ( int arr[][5] ) { ... }
甚至

void bar ( int arr[5][5] ) { ... }
在这三种情况下,
arr
都是指向
int
的5元素数组的指针。我更喜欢显式地写出指针类型,因为这就是实际发生的事情;其他人更喜欢使用2D数组语法,因为它更易于阅读

关于
(*p)[3]
的问题

int b[2][3]={{10,20,30},{40,50,60}};
//两个3个整数值的一维数组。第一个数组是b[0],第二个数组是b[1]

这里b将返回一个指向3个整数值的一维数组的指针。b返回我们
int(*)[3]
。这意味着指针是大小为3的一维数组

所以
*p=b;//无效。
但是
(*p)[3]=b;//有效。

因为p是指向三个元素数组的指针

如果打印p或*p或p[0]或&p[0][0],则它将打印第一个一维数组的第一个元素地址


如果打印p+1或*(p+1)或p[1]或&p[1][0],则它将打印第二个一维数组的第一个元素地址

C中的数组只是连续的内存块,每个内存块有一个
sizeof
元素。您可以有一个指向该内存的指针。您还可以将指针存储在此内存中。也许最有趣的是指向指针数组的指针,
void**p[3]
!希望能有帮助。是每个人的必读读物,初学者和退伍军人都一样。在int(*p)[3]的情况下,你已经证明p指向第一个整数,但事实并非如此。这就是我投反对票的原因。@Rahul,p确实在物理意义上指出了这一点,但从抽象层来说,你仍然必须告诉他你想要从数组中得到哪个条目。我试图通过将p指向数组的“before”来改进。如果您对如何更好地表示抽象有任何想法,请让我知道。在您的表示中,它显示p指向第一个元素,但实际上它表示整个数组。您的表示令人困惑。
void bar ( int arr[][5] ) { ... }
void bar ( int arr[5][5] ) { ... }
int b[2][3]={{10,20,30},{40,50,60}};