详解下c语言下的多维数组和指针数组

在实际c语言编程中,三维及以上数组我们使用的很少,二维数组我们使用得较多。说到数组,又不得关联到指针,因为他们两者的联系太紧密了。今天我们就详细介绍下c语言下的多维数组(主要是介绍二维数组)和指针。

一、二维数组

1.1,存储格式

一般大家看待二维数,都会把它看作一张表格,例如一个int a[3][4]的数组:

实际上,计算机中二维数组是以顺序的方式存储的,其内部存储格式如下,还是以int a[3][4]为例子:

1.2,二维数组声明和访问

我们可以通过如下方式进行二维数组声明和初始化:

cpp 复制代码
    char c[3][10]; //声明一个char类型的二维数组,它是包含3个长度为10的char数组
    int a[3][4] = {1,2,3,4,5,6,7,8,9,10,11,12}; //声明并初始化一个int类型的二维数组并初始化

二维数组的访问:

cpp 复制代码
    int a[3][4] = {1,2,3,4,5,6,7,8,9,10,11,12};

    for(int i=0;i<3;i++){
        for(int j=0;j<4;j++){
            printf("the element a[i][j] is %d\n", a[i][j]);
        }
    }

我们也可以利用指针的形式进行访问(数组的名字实际代表的数组首地址):

cpp 复制代码
    int a[3][4] = {1,2,3,4,5,6,7,8,9,10,11,12};

    for(int i=0;i<3;i++){
        for(int j=0;j<4;j++){
            printf("the element a[i][j] is %d\n", *(*(a+i)+j));
        }
    }

二、指针数组

2.1,指针数组存储格式

指针数组代表某一数组中的所有元素都是指针,其内部存储格式如下,我们以int *p[3]为例:

具体代码如下:

cpp 复制代码
int main() {



    int a = 100;
    int b = 200;
    int c = 300;

    int *p[3] = {&a, &b, &c};

    printf("the a address is %x\n", p[0]);
    printf("the a address is %x\n", p[1]);
    printf("the a address is %x\n", p[2]);

    return 0;
}

2.2,指针数组的声明和访问

我们可以通过如下方式进行指针数组的声明和初始化;

cpp 复制代码
    char *c[10];//声明一个包含10个char类型指针的数组
    int a = 100;
    int b = 200;
    int c = 300;

    int *p[3] = {&a, &b, &c};//声明一个包含3个int类型指针数组,并进行了初始化

指针数组的访问,我们可以通过如下两种方式进行指针数组指向内容的访问:

cpp 复制代码
int main() {

    int a = 100;
    int b = 200;
    int c = 300;
    int *p[3] = {&a, &b, &c};

    for(int i=0;i<3;i++){
        printf("the element i point to value is %d\n", *p[i]);
    }
    for(int j=0;j<3;j++){
        printf("the element i point to value is %d\n", **(p+j));
    }
    return 0;
}

三、二维数组与指针数组的比对

我们可以看到,对于二维数组和指针数组,我们都可以通过*(*(a+i)+j)的方式去访问,于是很多人误认为二维数组和指针数组是同一个东西,然两者其实还是有区别的。

对于二维数组

复制代码
char a[3][4] = {{'t','p','c'},{'i','s'},{'m','a','n'}}

无论每个数组中元素是否存储值,它的存储空间必需为sizeof(char)*3*4的。

二维数组元素访问(*(*(a+i)+j)),a的地址在程序编译阶段即可知道,我们获取数组某个元素,然后如下进行:

  • 1,取a的地址值
  • 2,取i的值,得知需要获取跨过的行长度(sizeof(char)*4*i),然后加到a地址值上
  • 3,取j的值,得知需要获取跨过的元素长度(sizeof(char)*j),然后加到上一步得到的地址上
  • 4,从第3步获取的地址,得到需要取得的元素的地址,从中取出值

对于指针数组

复制代码
char *a[3] = {"tpc","is","good"};

a中存在4个char类型指针,每个指针指向的一个char类型数组,但是每个数组的长度不一样。

指针数组元素访问(*(*(a+i)+j)),a的地址在程序编译阶段即可知道,我们需要获取数组某个元素,需要如下进行:

  • 1,取a的地址值(假设为100)
  • 2,取i的值,得知需要跨过的元素的字节长度(sizeof(char *)*i,然后的到具体元素的地址,值为100+sizeof(char *)*i(假设求出来为104)
  • 3,根据地址值104(因为a[i]为指针,我们需要根据指针值再去获取指向内容),我们得到内部存储地址为0x4071d4
  • 4,取j的值,得知需要跨过的元素字节长度(sizeof(char)*j)(假设j为1),那么我们得到需要取得元素的地址为0x4071d4+sizeof(char)*1 = 0x4071d5
  • 5,从0x4071d5中取出内容(对应图中的's')

四、数组指针

对应一个二维数组,如果我们需要通过声明一个指针来指向它,可以通过如下方式:

cpp 复制代码
int main() {

    int a[2][3] = {1,2,3,4,5};
    int (*p)[3] = a;

    printf("the address of a is %d\n", a);
    printf("the value of p is %d\n", p);

}

我们通过如下方式利用指针访问a中元素。

  • 1,获取指针p存储的值,得到a的地址,a为一个包含2个含有3个元素的数值
  • 2,我们通过p+i,及a+i获取a中对应2个数组元素的首地址
  • 3,我们通过*(p+i)+j,获取对应数组元素中的具体元素地址
  • 4,我们通过*(*(p+i)+j),获取到具体的元素值
cpp 复制代码
int main() {

    int a[2][3] = {1,2,3,4,5};
    int (*p)[3] = a;

    for(int i=0;i<2;i++)
        for(int j=0;j<3;j++)
            printf("the element a[%d][%d] is %d\n", i, j, *(*(p+i)+j));

}
相关推荐
小郝 小郝34 分钟前
【C语言】strstr查找字符串函数
c语言·开发语言
Dovis(誓平步青云)2 小时前
【数据结构】排序算法(中篇)·处理大数据的精妙
c语言·数据结构·算法·排序算法·学习方法
nuo5342022 小时前
黑马 C++ 学习笔记
c语言·c++·笔记·学习
电星托马斯14 小时前
C++中顺序容器vector、list和deque的使用方法
linux·c语言·c++·windows·笔记·学习·程序人生
march_birds19 小时前
FreeRTOS 与 RT-Thread 事件组对比分析
c语言·单片机·算法·系统架构
小麦嵌入式20 小时前
Linux驱动开发实战(十一):GPIO子系统深度解析与RGB LED驱动实践
linux·c语言·驱动开发·stm32·嵌入式硬件·物联网·ubuntu
jelasin20 小时前
LibCoroutine开发手记:细粒度C语言协程库
c语言
篝火悟者21 小时前
自学-C语言-基础-数组、函数、指针、结构体和共同体、文件
c语言·开发语言
神里流~霜灭1 天前
蓝桥备赛指南(12)· 省赛(构造or枚举)
c语言·数据结构·c++·算法·枚举·蓝桥·构造
双叶8361 天前
(C语言)单链表(1.0)(单链表教程)(数据结构,指针)
c语言·开发语言·数据结构·算法·游戏