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}};