指针数组和数组指针

指针数组:首先它是一个数组,数组的元素都是指针。它是“储存指针的数组”的简称。int *p1[10];
数组指针:首先它是一个指针,它指向一个数组。它是“指向数组的指针”的简称。   int (*p2)[10];

这里需要明白一个符号之间的优先级问题,关键在于p1、p2先和谁结合。
“[]”的优先级比“*”要高。p1 先与“[]”结合,构成一个数组的定义,数组名为 p1,int *修饰的是数组的内容,即数组的每个元素。那现在我们清楚,这是一个数组,其包含 10 个指向 int 类型数据的指针,即指针数组。
至于 p2 就更好理解了,在这里“()”的优先级比“[]”高,“*”号和 p2 构成一个指针的定义,指针变量名为 p2,int 修饰的是数组的内容,即数组的每个元素。数组在这里并没有名字,是个匿名数组。那现在我们清楚 p2 是一个指针,它指向一个包含 10 个 int 类型数据的数组,即数组指针。

我们可以借助下面的图加深理解:

上述摘自: http://www.cnblogs.com/li-chong

关于指针数组和数组指针的代码:

#include <iostream>
using namespace std;
int main()
{
    int *p1[3];
    int (*p2)[3];
    int a[3] = {1,2,3};
    int b[2][3] = {{1,2,3}, {4,5,6}};
  
    p1[0] = &a[0];//int *
    p1[1] = &a[1];//int *
    p1[2] = a + 2;//int *
    for (int i = 0; i < 3; i++)
        cout << *p1[i] << " ";
    //output:1 2 3
  
    p2 = &a;      //int (*)[3]
    for (int i = 0; i < 3; i++)
        cout << (*p2)[i] << " ";
    //output:1 2 3
  
    p2 = &b[1];   //int (*)[3]
    for (int i = 0; i < 3; i++)
        cout << (*p2)[i] << " ";
    //output:4 5 6
}

明确两点

1. int a[3] = {1, 2, 3};

a是数组的首元素的首地址,具体地说是一个具有3个整型变量的数组的名字,而&a是整个数组的首地址,其值相同但意义不同。
编译器根据我们提供的类型和数组大小,为我们分配了适当大小的存储区域,并且把这块存储区域叫做a。请注意 :&a,它的类型是“指向具有 3 个整型变量数组的指针“,简而言之&a是一个数组指针。

2. &a+1

式子&a+1表示的是指针加法运算,而不是普通的数值加法运算,之所以会这样是因为&a是一个指针而非普通数值(虽然它本质上也是一个整数)。假如此时&a=0xFFFF5700,那么&a+1是多少呢?答案是:取决于&a的类型 。
  a) 如果&a是一个指向char型的指针,那么&a+1 = 0xFFFF5701
  b) 如果&a是一个指向short型的指针,那么&a+1 = 0xFFFF5702
  c) 如果&a是一个指向int型的指针,那么&a+1 = 0xFFFF5704 (32位机器)
  d) 如果&a是一个指向某种结构体struct foo的指针,那么&a+1 = 0xFFFF5700+sizeof(struct foo)
  ……

指针加1不是指针内容简单地加1,而是让指针指向下一个数据,这个数据的类型就是指针指向的类型,所以指针的加法究竟会让这个指针指向哪里,取决于这个指针指向的数据类型。
因此,综上所述,当&a与整数1做加法时,实际上是指针的加法,加1的含义是:令指针a指向下一个数据 ,下一个数据是啥?当然是紧挨着的下一个具有3个整型变量的数组了(因为&a的类型是指向具有3个整型变量的数组的指针)。

 

原文地址:https://www.cnblogs.com/mrsandstorm/p/5701595.html