前言:在上一篇文章中,笔者介绍了指针和数组的内存分配以及初始化,这篇文章来整理下关于数组访问的两种方式。
数组的下标引用和指针访问
在正式开始介绍多维指针和多维数组之前,笔者要先介绍一些关于数组下标引用和指针访问的相关内容。了解这些内容,会更加有助于我们理解后面的多维指针和多维数组。
1.以下标引用的方式访问数组
在使用数组的场合中,我们常见的一种访问方法是使用下标访问数组元素,如:array[2] = 1
,此语句是将该数组的第三个元素赋值为1.[ ]符号中的数字可以认为是在数组基地址上的偏移量,可以通过改变这个偏移量来访问整个数组。
2.以指针访问的方式访问数组
除了使用偏移量的方法,我们还可以使用指针的方法来访问数组,即间接引用的方式。如:*(array+2) = 1
,同上面的代码一样,也是对该数组的第三个元素进行赋值。
3.下标引用和指针访问的执行效率问题
对于这两种不同的访问数组的方式,它们的执行效率也不同,在这里先给出结论:指针访问的效率 >= 下标引用的效率。接下来我们来说说,为什么使用指针进行间接访问的效率会优于小标引用的效率。
-
下标引用的效率
现在假设有如下代码,执行对整个数组的初始化过程:
int array[10];
for(int i = 0;i < 10;i++)
{
array[i] = 0;
}
在这里我们还是假设编译器中int类型占4个字节,在执行array[i] = 0
时,编译器会将其转化为类似*(array + (i*4)) = 0
形式。在整个执行10次的循环中,意味着也进行了10次乘法运算操作和10次加法运算操作。
-
指针访问的效率
假设有如下代码,执行对整个数组的初始化过程:
int array[10];
for(int *ptr = array; ptr < array+10; ptr++)
{
*ptr = 0;
}
这里是将指针一开始指向数组首地址,然后每次向后移动一个数组元素,这里是每次移动4个字节,即每次对指针地址+4。在整个过程中只进行了10次加法运算。同上对比可得,对于数组操作来说,指针访问的效率是优于下标引用的。
4.下标引用和指针访问的优先级问题
关于这个问题,笔者还是先给出结论,再举例进行阐述。
结论:下标引用优先级 > 指针访问优先级。
假设我们现在有以下两个数组的声明:
int *array1[10];
int (*array2)[10];
关于上述声明,乍一看很容易混淆,但其实这只是一个关于结合优先级的问题。在看这些声明时,需要记住下标优先级高于指针,并且如果出现了( ),那么它的优先级一定是最高的*。
int *array1[10]
在和[ ]同时出现的时候,我们先结合优先级高的[ ]来看,即它先声明了一个含有10个元素的数组array1
,然后将剩下的int *
组合,可以知道这个数组里面的每个元素,都是一个指向整型类型的指针变量。也就是说,这是一个含有10个指针变量的指针数组*。int (*array2)[10]
这里的声明中出现了( ),由于( )的优先级最高,所以我们先看(*array2)
,即array2
是一个指向某种类型的指针变量。再结合剩下的int [10]
,可以知道这个指针变量指向的数据类型是含有10个元素的整型数组。也就是说,这是一个数组指针,指向一个10元素整型数组。
总结:关于数组的下标引用和指针访问,可以根据需要效率和可读性选择不同的方式,使用指针效率固然会得到提高,但在复杂场景中,会牺牲代码可读性。关于声明指针数组还是数组指针,可以根据*和 []的优先级进行需求组合。