【C语言】数组指针和指针数组的用法、区别

    技术2025-05-27  16

    文章目录

    1.数组指针1.1 基本概念1.2 定义格式1.3 扩展:指向二维数组的数组指针如何遍历二维数组元素? 2.指针数组2.1 基本概念2.2 定义格式 数组指针和指针数组,从字面上区分的方法就是:本质看最后两个字。例如数组指针的本质就是一个指针,一个指向数组的指针;而指针数组的本质就是一个数组,一个成员都是指针的数组。

    1.数组指针

    1.1 基本概念

    数组指针,即指向一个数组的指针。可以指向一维数组,也可以指向二维数组(三维及以上数组一般不用)。

    1.2 定义格式

    int (*p)[n]=NULL; p = 数组名; //当数组是一维数组时,直接写数组名编译器会警告,但是运行正常。写成“&数组名”不会警告。对于二维及以上数组,直接写数组名不会警告。

    解析:

    类型说明符 (*指针变量名)[长度]。

    其中“类型说明符”为所指数组的数据类型。* 表示其后的变量p是指针类型,它指向的对象是一个整体,即一维数组(不能拆开此数组)。

    【注1】

    首先 运算符[ ] 的优先级比 * 高,虽然在优先级表中 [ ] 的优先级最高,其次是 ( ) 。但是 ( ) 有强制结合的功能,所以这里p是和*结合的,而不是[]。

    【注2】

    当数值指针指向一维数组时,n是一维数组元素的个数。 当数值指针指向二维数组时,n是二维数组的列数,即按行拆分成一维数组后,一维数组的个数。

    【注3】

    数组指针也叫“行指针”,原因是数组指针指向的数组不管是一维数组,还是二维数组,指针变量p指向的都是行。

    【例】用“数组指针”分别指向并遍历一维数组和二维数组的所有元素。

    #include <stdio.h> int main(void){ int i,j; int a[5]={1,2,3,4,5}; int b[3][4]={1,2,3,4,5,6,7,8,9,10,11,12}; int (*p1)[5]=NULL; int (*p2)[4]=NULL; p1=a; //会警告提示指针类型不匹配,但是可以运行正常,应该是C隐式进行类型转换。写成 p1=&a;无警告无错误 p2=b; printf("遍历输出一维数组元素\n"); //通过数组指针来遍历输出一维数组a的元素 for(i=0;i<5;i++){ printf("%2d", *((*p1+0)+i) ); } printf("\n"); printf("遍历输出二维数组元素\n"); for(i=0;i<3;i++){ for(j=0;j<4;j++){ printf("%3d", *(*(p2+i)+j) ); } printf("\n"); } return 0; }

    运行结果:

    1.3 扩展:指向二维数组的数组指针如何遍历二维数组元素?

    在上例中,数组指针p2指向二维数组b。

    下面探索一下如何使用数组指针 p2 来访问二维数组b中的每个元素。

    数组指针p2指向二维数组 b 的开头,也即第 0 行;p2+1前进一行,指向第 1 行。

    *(p2+1)表示取地址上的数据,也就是整个第 1 行数据。注意是一行数据,是多个数据,不是第1 行中的第0个元素。

    *(p2+1)+1表示第 1 行第 1 个元素的地址。怎么理解?

    *(p2+1)单独使用时表示的是第1行整体数据,放在表达式中会被转换为第 1 行数据的首地址,也就是第 1 行第 0 个元素的地址,因为使用整行数据没有实际的含义,编译器遇到这种情况都会转换为指向该行第 0 个元素的指针;就像一维数组的名字,在定义时或者和 sizeof、& 一起使用时才表示整个数组,出现在表达式中就会被转换为指向数组第 0 个元素的指针。

    *(*(p2+1)+1)表示第 1 行第 1 个元素的值。很明显,增加一个 * 表示取地址上的数据。

    2.指针数组

    2.1 基本概念

    具有指针类型元素的数组称为指针数组,实质上就是一个数组。

    2.2 定义格式

    类型说明符 *指针变量名[长度];

    【注】

    如:int *p[n]; //int *(p[n])也是一个指针数组,这里小括号可有可无。 []优先级比 * 高,所以先与p结合成为一个数组,然后int *说明该数组中每个元素的数据类型都是“整形指针类型”。

    Processed: 0.014, SQL: 9