数组指针
指针数组就是数组中存储的元素都是指针,即类型相同的指针变量。定义一维指针数组的语法格式如下:
类型名* 数组名[常量表达式];
上述语法格式中,类型名表示该指针数组的数组元素指向的变量的数据类型,符号“*”表示数组元素是指针变量。
根据上述语法格式,假设要定义一个包含5个整型指针的指针数组,示例代码如下:
int* parr[5];
上述代码定义了一个长度为5的指针数组parr,数组中元素的数据类型都是int。由于“[]”的优先级比“”高,数组名parr优先和“[]”结合,表示这是一个长度为5的数组,之后数组名与“*”结合,表示该数组中元素的数据类型都是指针类型。parr数组中的每个元素都指向一个int类型变量。
指针数组的数组名是一个地址,它是指针数组的起始地址,同时也是第一个元素的地址,由于指针数组中的元素是一个地址,即指针数组名指向一个地址,因此指针数组的数组名实质是一个二级指针。
指针数组在C语言编程中非常重要,为了让读者能够更好的掌握指针数组的应用,下面带领读者使用指针数组处理一组数据。
有一个float类型的数组存储了学生的成绩,其定义如下:
float arr[10] = {88.5,90,76,89.5,94,98,65,77,99.5,68};
定义一个指针数组str,将数组arr中的元素取地址赋给str中的元素,示例代码如下:
float *str[10]; //定义一个float类型的指针数组
for(i = 0; i < 10; i++)
{
str[i] = &arr[i]; //将arr数组中的元素取地址赋予str数组元素
}
上述代码中,首先定义了一个float类型指针数组str,然后使用for循环将arr数组中的元素地址赋给了str数组元素,则数组arr与数组str之间的关系如图1所示。
图1 数组arr与数组str的关系
指针数组str中存储的是数组arr中的数组元素地址,可以通过操作指针数组str对这一组成绩进行排序,而不改变原数组arr,例如,使用冒泡排序对数组str进行从大到小的排序,示例代码如下所示:
for(i = 0; i < 10-1; i++)
{
float *pTm; //定义临时指针用于交换
for(j = 0; j < 10-1-i; j++)
{
if(*str[j] < *str[j+1])
{
pTm = str[j];
str[j] = str[j+1];
str[j+1] = pTm;
}
}
}
上述代码使用冒泡排序对指针数组str从大到小排序,在str数组中,每个元素都是一个指针,因此,在比较元素大小时,使用“*”符号取值进行比较。
排序完成之后,数组arr并没有改变,只是指针数组str中的指针指向发生了改变,此时数组str与数组arr之间的关系如图2所示。
图2 排序完成后数组str与数组arr之间的关系
当然,如果在排序过程中,不交换指针数组str中的指针,而交换指针指向的数据,则数组arr就会被改变。交换str中指针指向的数据,示例代码如下:
for(i = 0; i < 10-1; i++)
{
float tpm; //定义一个float的类型的临时变量
for(j = 0; j < 10-1-i; j++)
{
if(*str[j] < *str[j+1]) //交换指针指向的数据
{
tpm = *str[j];
*str[j] = *str[j+1];
*str[j+1] = tpm;
}
}
}
上述代码在排序时交换了str数组中指针指向的数据,排序完成之后,指针数组str与数组arr之间的关系如图3所示。
图3 交换str数组中指针指向的数据
由图3可知,在排序中交换了指针指向的数据,则arr数组改变,而指针数组str中指针的指向并没有改变,但其指向的位置处数据发生了改变,因此指针数组str也相当于完成了排序。
由上述示例可知,使用指针数组处理数据更加灵活,正因如此,指针数组的应用很广泛,特别是在操作后续章节学习的字符串、结构体、文件等数据时应用更加广泛。