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

文章目录

    • 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 

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;
}

运行结果:
【C语言】数组指针和指针数组的用法、区别_第1张图片

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

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

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

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

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

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

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

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

2.指针数组

2.1 基本概念

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

2.2 定义格式

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

【注】

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

你可能感兴趣的:(C语言,c语言,数组指针,指针数组,指针,二维数组)