数组指针
在揭开数组指针神奇的面纱之前,我们先来探讨一下数组是否有自己特定的类型呢?
1. 数组类型
我们知道数组是相同类型变量的有序集合。例如 int a[5] = {0};
,其含义就是 5
个 int
类型变量集合在一起由数组 a
管理。那么我想问一下,数组 a
的类型是什么呢?
如果读者是正在C语言求学道路上的话,那么你的答案应该是 int
类型。但是我想说的是,很不好意思,这个答案是错的,那么接下来就为大家揭晓答案。
首先,我们要明确一点:
在 C 语言中,数组有自己特定的类型。
那么,数组的类型又是什么呢?
数组的类型由数组中的元素类型和数组大小决定。
因此,上面所定义的数组 a
的类型是 int[5]
,而不是 int
。
2. 定义数组类型
明白数组的类型之后,我们就可以通过定义数组类型,来换一种方式来创建数组。
在 C 语言中,可以通过 typedef
关键字为数组类型重命名:
typefet type(name)[size];
int
为数组中元素的数据类型name
为将要创建的数组类型的名字size
为将要创建的数组的元素个数
示例:
- 定义数组类型
// 定义数组中元素类型为 int、数组元素个数为 5 的数据类型为 AINT5
// 定义数组中元素类型为 float、数组元素个数为 10 的数据类型为 AFLOAT10
typedef float(AFLOAT10)[10];
- 声明数组
// 声明一个数据类型为 AINT5、数组名为 iArray 的数组
AINT5 iArray;
// 声明一个数据类型为 AFLOAT10、数组名为 fArray 的数组
AFLOAT10 fArray;
现在大家应该明白了数组类型怎么去创建了吧。但是又出现个问题,比如 int
类型占 4 个字节、char
类型占 1 个字节,那么数组类型的大小是多少呢?
下面通过一个例子来说明一下:
typedef int(AINT5)[5];
AINT5
数组类型说包含的数组元素为int
类型,共包含 5 个元素- 由于每个
int
类型占用4个字节的内存空间 - 因此,
AINT5
所占用的内存空间为 20 个字节
同理,通过上面可以推导出一个计算公式:
sizeof(TypeArray) = sizeof(type)·size
TypeArray
为数组类型type
为数组类型中元素的类型size
为数组类型所包含的数组元素个数
那么,对于任意种类的数组类型所占内存空间的大小都可以通过这个公式进行计算,同时通过某个数组类型创建的数组所占空间的大小即为数组类型所占空间的大小
。
到此为止,我们对数据类型应该了如指掌了吧。下面开始真正的话题 数组指针
。
3. 数组指针
前面我们讲了一大堆关于数组类型的本质、数组类型的创建。那么你们可能会想数组类型也没有多大神奇,无非不就是换一种方式声明声明数组吗?我想说的是,有了数组类型,我们便可以定义数组指针了,你们想一想是不是呢。
首先,我们先来回想一下指针声明的语法结构:
(type)* name = NULL;
type
为声明的这个指针的类型name
为这个指针的名字
通过指针声明的语法结构,我们可以定义 int
、float
、char
等类型的指针。那么,现在有了数组类型,不就轻而易举的创建数组指针了吗。
(1)可以数组类型定义数组指针:
ArrayType* pointer;
ArrayType
为数组类型pointer
为数组指针的名字
(2)可以通过数据类型直接定义:
type(*pointer)[n];
pointer
为数组指针变量名type
为指向的数组的类型n
为数组的元素个数
截止到现在,我们明白了数组指针怎么创建,下面我们通过一个 demo
加深一下印象。
#include <stdio.h>
// 对数组元素为 int、数组元素个数为 5 的数组重命名为 AINT5
typedef int(AINT5)[5];
// 对数组元素为 flaot、数组元素个数为 10 的数组重命名为 AFLOAT10
typedef float[AFLOAT10][10];
// 对数组元素为 char、数组元素个数为 9 的数组重命名为 ACHAR9
typedef char[ACHAR9][9];
int main()
{
// 声明一个数组类型为 AINT5、数组名字为 iArray 的数组
AINT5 iArray;
// 声明一个数组元素类型为 float、数组元素个数为 10、数组名字为 fArray 的数组
float fArray[10];
// 声明一个类型为 AFLOAT10、名字为 pfArray,并且值为数组 fArray 的地址的数组指针
AFLOAT10* pfArray = &fArray;
// 声明一个数组类型为 ACHAR9、数组名字为 cArray 的数组
ACHAR9 cArray;
// 声明一个类型为 char、元素个数为 9、名为 pc 并且值为 cArray 的数组指针
char(*pc)[9] = &cArray;
/*
首先 cArray 是数组 cArray 首元素的地址,其类型为 char*
char(*pcw)[4] 为一个数组指针,其要指向某个数组存储空间
因此 char(*pcw)[4] = cArray; 报错
*/
// char(*pcw)[4] = cArray;
int i = 0;
// 输出数组类型 AINT5 所占内存空间、数组 iArray 的大小
printf("%d, %d\n", sizeof(AINT5), sizeof(iArray));
for(i=0; i<10; i++)
{
// pfArray 为一个指针,其保存的值为数组 fArray 的地址,那么 *pfArray 所指向的内容便是 fArray,即 *pfArray = fArray
// (*pfArray)[i] = i == fArray[i] = i
(*pfArray)[i] = i;
}
for(i=0; i<10; i++)
{
// 将数组 fArray 中的数组元素遍历输出
printf("%f\n", fArray[i]);
}
/*
由于 pc 是一个指针,由指针运算得:
pc+1 = (unsigned int)pc + a·sizeof(*pc)
其中 sizeof(*pc) 为 pc 所指向的目标,即数组 cArray
(unsigned int)pc 为 pc 所保存的值,即数组 cArray 的地址值
pc+1 = &cArray + 9
*/
/*
由于 pcw 是一个指针,由指针运算得:
pcw+1 = (unsigned int)pcw + a·sizeof(*pcw)
其中 sizeof(*pcw) 为 pcw 所指向的目标为:有 4 个 char 类型的元素构成,因此 sizeof(*pcw) = 4
(unsigned int)pcw 为 pcw 所保存的值,即数组 cArray 首元素地址值
pcw+1 = &cArray + 9
*/
printf("%p, %p, %p\n", &cArray, pc+1, pcw+1);
return 0;
}
上面这个 demo
中所有的代码的含义都通过注释的方式在文中标注出。同时,通过这个 demo
我们可以很清晰的对数组类型所占空间的大小及数组类型的创建、数组指针的创建及使用了如指掌。
通过上面这个 demo
能够得出如下结论:
- 指针运算适用于任何类型的指针
- 数组指针与普通指针类似,无非指向的内容的是
数组
而已