在之前的文章中介绍过可以用数组名作函数的参数,并多次强调:数组名代表数组首元素的地址。用数组名作函数的参数,传递的是数组首元素的地址。很容易推想:用指针变量作函数形参,同样可以接收从实参传递来的数组首元素的地址(此时,实参是数组名)。
编写程序:
运行结果:
程序分析:
程序中select_sort函数的实参是一维数组名a,形参是基类型为整型的指针变量p。在调用此函数时,通过虚实结合,将主函数中的数组a的首元素地址传递给形参p,因此p就指向数组a的首元素。在select_sort函数中通过对指针变量p的操作,可以访问a数组的各元素,例如*(p+1)就是a[1],*(p+j)就是a[j],*(p+k)就是a[k],*(p+i)就是a[i]。在执行select_sort函数的过程中,依照选择法的算法对数组a的元素进行排序。在调用select_sort 函数结束后,a数组中的元素已经按由小到大的顺序排列好了。在主函数中顺序输出数组a的各元素,就是已排好序的数列。
C++编译系统将形参数组名一律作为指针变量来处理。例如,
void select sort(int array[].int n)
在编译时是将形参数组名array按指针变量处理的,相当于将函数的首部写成
void select_sort(int =array,int n)
以上两种写法完全等价。在调用该函数时,系统会建立一个指针变量array,用来存放从主调函数传递过来的实参数组首元素的地址。为了证明这一结论,可以上机做一个测试:先在main函数中用sizeof(a)测定数组a的长度,结果为40,表示它有10个元素,每个元素占4字节。再在select_sort 函数中用sizeof(array)测定array 的长度,结果为4,而不是40。这证明了系统是把array作为指针变量来处理的(一般C++系统对指针变量分配4字节)。
这就清楚地说明:实际上在函数调用时并不存在一个占有存储空间的形参数组,只有指针变量。用下标法和指针法都可以访问一个数组(如果有一个数组a,则a[i]和*(a+i)无条件等价),用下标法表示比较直观,便于理解。有的初学者愿意用数组名作形参,以便与实参数组对应,看起来比较清楚好懂。用户可以认为有一个形参数组,它从实参数组那里得到起始地址,因此形参数组与实参数组共占同一段内存单元,在调用函数期间,如果改变了形参数组的值,也就是改变了实参数组的值,在主调函数中可以利用这些已改变的实参数组的值。这种形象化的方法对初学者是有好处的。专业人员往往喜欢用指针变量作形参,程序显得比较专业和高效。
在此基础上,还要说明一个问题:实参数组名a代表一个固定的地址,或者说是指针型常量,因此要改变a的值是不可能的。如
a++; //语法错误,a是常量,不能改变
而形参数组名是指针变量,并不是一个固定的地址值。它的值是可以改变的。在函数调用开始时,它接收了实参数组首元素的地址,但在函数执行期间,它可以再被赋值。如
f(array[],intn)
{ cout<<array; //输出array[0]的值
array=array+3; //指针变量 array 的值改变了,指向array[3]
cout<<*arr<<endl; //输出array[3]的值
}
用指针变量可以指向一维数组中的元素,也可以指向多维数组中的元素。但在概念上和使用上,多维数组的指针比一维数组的指针要复杂一些。