C语言:关于指针数组和数组指针

一、指针数组
按照语文的理解,我们知道指针数组的中心词是数组,而指针是用来修饰数组的定语。事实上在C语言中也确实是这样,指针数组,就是一个数组,一个存放指针的数组。它常用于指向若干字符串,这样使字符串处理更加灵活方便。
下面我们通过几个例子来理解一下指针数组:

int* arr1[10];
char* arr2[4];
char** arr3[5];

这三个语句是指针还是数组呢? 我们知道,运算符[ ]的优先级是要高于的,所以在这里,数组名会先和[ ]结合,再和结合。那么这三个语句所定义的变量就都是数组而不是指针了。具体怎么理解这三条语句呢?下面就一一详细解释给大家:arr1是一个存放了10个类型为int*变量的数组。那么经类比,arr2就是存放了4个类型为char*类型的变量,arr3就是存放了5个类型为char**的变量。

现在对指针数组有一个初步的了解了吧,我们知道,指针和数组是很类似的,那么指针数组和二维数组之间有什么区别呢?接下来我们具体说一下指针数组和二维数组的对比:

1 . 二维数组:如

char str1[3][4];

只要定义了一个数组,无论赋不赋值,系统都会给它分配相应的空间,而且一定是连续的空间。其每个元素都是表示一个字符,我们可以通过下标对其元素进行修改。

2 . 指针数组:如

char *str2[3];

代表一个数组,存放了3个类型为char*的变量,系统至少会分配3个连续的空间来存储这3个元素,表示str2是一个3个元素的数组,每个元素是一个指向字符型数据的指针。

我们来举两个例子说明一下二维数组和指针数组在内存中的存储方式:

char str1[3][5] = {"I","am","good"};
char *str2[3] = {"I","am","good"};

他们在内存中的存储方式如下图:
这里写图片描述

第一幅图是二维数组的存储方式,第二幅图是指针数组的存储方式。我们可以看出,系统给str1分配了3* 5个字节的空间, 而且是连续的。而给str2分配的空间取决于具体字符串的长度,而且不一定连续。

所以,二者的优缺点也就显而易见了:
指针数组中每个元素所指的字符不必限制在相同 字符长度,而且访问数组的一个元素是用指针间接进行的,效率比下标要高,但二维数组却可以通过下标很方便的修改某一元素的值,指针数组不行。

二、数组指针
同样的,按照语文的理解,中心词是指针,数组是修饰指针的定语,事实上C语言中也是这样。数组指针,是一个指针,指向数组的指针,它存放的是数组首元素的地址。我们通过一个例子来具体说明一下:

int (*p)[10];

上面我们已经说过,运算符[ ]优先级要高于,所以这里加了(),那么就是p先和*结合,在与[ ]结合。那么显然,这是一个指针。它是什么意思呢,它是指向一个存放了类型为int的10个变量的数组的指针,存放的这个数组首元素地址,也就是相当于存放了一个指针的地址。

那么数组指针具体有什么用呢,它既然是指向一个数组的指针,可以存放数组的地址吗?答案是肯定的,我们看下面这个代码:

int arr[10]={ 0 };
int *p1=&arr;
int (*p2) [10]=&arr;

上面所述的第二行语句的意思是:将数组的地址存放在一个int类型的指针变量中,这显然不行的。int型指针变量只能存放一个int类型变量元素的值,怎么可以存放一个数组10个元素的变量呢?而第三行代码就很好的解决了这个问题:第三行代码定义了一个指向含有10个int型变量数组的指针,用来存放数组arr的地址,恰恰好。

介绍完了指针数组和数组指针,最后我们再强调一下最核心的点:
1.指针数组,是一个数组,存放指针变量的数组。
2.数组指针,是一个指针,一个可以指向数组的指针。

猜你喜欢

转载自blog.csdn.net/windyj809/article/details/80080124