指向数组的指针

1.指针数组和数组指针的概念

指针数组:指针数组是一个数组,是指由指针构成的数组,在这个数组中的所有元素都是指针,每个指针占用相同的字节。

数组指针:数组指针是一个指针,是指一个数组的指针,数组两字表示这个指针指向一个数组的首地址,并且这个指针加1时移动的位置是整个数组的长度。

2.指针数组

一个可行的指针数组定义如下:

char *arr[4] = {"hello", "world", "xiang", "qian"};

这里的写法是*arr[4],则表示指针数组,如果是(*arr)[4],则表示数组指针。上面的代码中arr是一个有4个元素的数组,每个元素都是指针,因此arr占据的空间是14个字节,而后面的字符串呢?他们被分配在另一个内存区域,由arr指向他们,因此可以试着向字符串中多写入几个字母,再用sizeof(arr)输出观察,结果依然是16个字节。所以指针数组,相当于是把好几个指针放在了一个数组里,仅此而已。

3.指向数组的指针

对于一维数组,实际上数组的名字就是数组的首地址,数组的名字也可以当做指针使用。假设一个数组arr[5]存放了5个整型数字,在定义一个指针int *p = arr;那么arr[2]和p[2]的值是一样的。

而如果定义了一个数组指针指向了一个一维数组呢?如int (*p1)[5] = arr这时候相当于是一个指针,注意是一个!一个指针指向了一块内存区域,这块区域是个一维数组的首地址,而对这个指针进行加一操作的时候,这个指针实际上移动了整个数组长度的距离。这个可以类比来理解,指针之所以需要声明类型,是为了说明清楚指针它指向什么类型的数据,这样加一操作是才能知道移动多少距离,指向char的指针加一时移动1个字节,指向double的指针加一时移动8个字节。同样的道理,指向数组的数组指针如果写成int[5]  (*p1)这样会比较好理解,这就告诉我们p1这个指针加一时一次要移动5个int的距离。实际中不能这么写,这只是为了好理解。

对于一维数组的访问,使用普通指针就够了,如果使用数组指针反而会比较麻烦。

#include <iostream>
using namespace std;
int main() {

    int arr1[5] = {1, 2, 3, 4, 5};
    int *p1;
    int (*p2)[5] = &arr1;
    //p1 = &arr1[0];
    p1 = arr1;
    cout << sizeof(arr1) << endl;
    cout << &arr1 << '\t' << p1 << endl;
    cout << &arr1 + 1 << '\t' << p1 + 1 << endl;
    cout << endl;
    cout << &arr1 << '\t' << p2 << endl;
    cout << &arr1 + 1 << '\t' << p2 + 1 << endl;
    cout << p1[2] << '\t' << *(*(p2+0)+2)<< endl;    } 

代码输出为:

20

0x28fef4        0x28fef4

0x28ff08        0x28fef8


0x28fef4        0x28fef4

0x28ff08        0x28ff08

3       3


对于二维数组的访问,也可以使用普通指针或者数组指针。假设一个数组arr2[3][3],定义一个普通指针获取arr2[0][0]的地址后,就可以操作其所有的元素,本质上这个数组在内存中的位置是连续的,因此我们当然知道对指针增加几个单位后会指向哪个位置。而使用数组指针时,int (*p2)[3] = arr2;一定要记住p2后面的方括号里的数字要和数组的列数相同,因为这样对这个指针进行加一操作时,移动的单位就是数组的列数,相当于移动了一整行的距离。

#include <iostream>

using namespace std;

int main() {
    int arr2[3][3] = {{1, 2, 3},
                      {4, 5, 6},
                      {7, 8, 9}};
    for (int i = 0; i < 3; i++) {
        for (int j = 0; j < 3; j++)
            cout << arr2[i][j] << ' ';
        cout << endl;
    }
    int *p3 = &arr2[0][0];
    cout << p3[0] << ' ' << p3[7] << endl;
    int (*p4)[3] = arr2;
    cout << arr2 << '\t' << p4 << endl;
    cout << arr2 + 1 << '\t' << p4 + 1 << endl;
    cout << 0x28fee8 - 0x28fedc << endl;
    cout << *(*(p4+0)+1) << '\t' << *(*(p4+2)+0) << endl;

    return 0;
}

输出为:

1 2 3

4 5 6

7 8 9

1 8

0x28fedc        0x28fedc

0x28fee8        0x28fee8

12

2       7

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值