徐善通的随笔

千里之行, 始于足下



c语言使用数组指针遍历二维数组


数组指针和指针数组的区别

从名字上来看数组指针指针数组很容易混淆, 但是他们的区别是很大的

  • 数组指针: 数组指针是指向一个数组的指针, 本身只占用对应的类型的空间, 如 int类型, 则只占用4个字节
  • 指针数组: 指针数组是由多个指针构成的一个数组,数组中的每个元素都是一个指针,占用的空间 = 类型*长度

定义:

// 由于[]的优先级比*要高, 所以定义数组指针的时候一定要加小括号
int *pa[5]; // 指针数组, 占用20个字节
int (*pa1)[5]; // 数组指针, 占用4个字节

使用数组名遍历数组

#include <stdio.h>

int main()
{
    int arr[4][5] = {
        {1, 2, 3, 4, 5},
        {11, 12, 13, 14, 15},
        {21, 22, 23, 24, 25},
        {31, 32, 33, 34, 35},
    };

    for (int i = 0; i < 4; i++) {
        for (int j = 0; j < 5; j++) {
            printf("%4d", *(*(arr+i))+j); // 对数组名进行两层解引用
        }
        printf("\n");
    }

    return 0;
}

解析

在c语言中,数组名存储的是数组第一个元素的地址, 可以得出arr = &arr[0], 所以, 数组名其实也相当于一个指针

arr+1 指向的其实是 arr[1], 而arr[1]里存储的是指向 arr[1][0]的地址,所以, 对arr+1进行解引用,得到的是arr[1][0]的地址,而不是值, 所以
*(arr+1) = &arr[1][0];

如果将*(arr+1)再加一, 那么提到的将会是arr[1][1]的地址, 故(*(arr+1)+1) = &arr[1][1],
如果再一次对其进行解引用, 那么得到的才是真正的值

*(*(arr+1)+1) = arr[1][1];

下面我们用代码试验一下

printf("arr指向的地址: %p\n", arr);
printf("arr[0]的地址:  %p\n", &arr[0]);
printf("\n");

printf("arr+1的地址:  %p\n", arr+1);
printf("arr[1]的地址:  %p\n", arr[1]);
printf("\n");


printf("arr[1][0的地址:  %p\n", &arr[1][0]);
printf("*(arr+1)的地址:  %p\n", *(arr+1));
printf("\n");

printf("*(*(arr+1))的值为:  %d\n", *(*(arr+1)));
printf("*(*(arr+1)+1)的值为:  %d\n", *(*(arr+1)+1));

结果为

arr指向的地址: 0x7ffeebacaaa0
arr[0]的地址:  0x7ffeebacaaa0

arr+1的地址:  0x7ffeebacaab4
arr[1]的地址:  0x7ffeebacaab4

arr[1][0的地址:  0x7ffeebacaab4
*(arr+1)的地址:  0x7ffeebacaab4

*(*(arr+1))的值为:  11
*(*(arr+1)+1)的值为:  12

可以看出, &arr[1] - &arr[0] = 0X14; 16进制的14等于10进制的20, 一个int占用4个字节, 20正好是5个元素, 也就是arr+1的跨度为一行

使用数组指针

#include <stdio.h>

int main()
{
    int arr[4][5] = {
        {1, 2, 3, 4, 5},
        {11, 12, 13, 14, 15},
        {21, 22, 23, 24, 25},
        {31, 32, 33, 34, 35},
    };

    // 定义数组指针,指向arr数组, 占用4个字节
    // 此处的[5], 5代表 如果p+1, 那么将会前进5*4 = 20个字节, 正好处于数组的下一行
    // 因为一个int占用4个字节, 所以是5*4, 如果对象为 double格式, 占用的将会是8个字节, 跟随数据类型来变化
    int (*pa)[5] = arr;

    for (int i = 0; i < 4; i++) {
        for (int j = 0; j < 5; j++) {
            printf("%4d", *(*(pa+i))+j);
        }
        printf("\n");
    }

    return 0;
}

打印结果

 shantong@mac  ~/c-project gcc array_pointer.c  && ./a.out
   1   1   1   1   1
  11  11  11  11  11
  21  21  21  21  21
  31  31  31  31  31

此处用法和上面的数组名一样, 其中的原理也是一样的, 但是可以通过指针来间接达成目的


作者: 徐善通
地址: https://www.xstnet.com/article-143.html
声明: 除非本文有注明出处,否则转载请注明本文地址


我有话说



最新回复


正在加载中....

Copyrights © 2016-2019 醉丶春风 , All rights reserved. 皖ICP备15015582号-1