来看看一个函数声明:
int sum_arr(int arr[], int n) //arr = array name, n = size
防护括号指出arr[ ]是一个数组,而方括号为空则表明,可以将任何长度的数组传递给该函数。但是实际情况并非如此:arr实际上并不是数组,而是一个指针!但是在编写函数其余部分时,可以将arr看作是数组。首先来看一个例子:
#include<iostream>
const int ArSize = 8;
int sum_arr(int arr[], int n);
int main()
{
int cookies[ArSize] = { 1, 2, 4, 8, 16, 32, 64, 128 };
int sum = sum_arr(cookies, ArSize);
std::cout << "Total cookies eaten: " << sum << "\n";
system("pause");
return 0;
}
int sum_arr(int arr[], int n)
{
int total = 0;
for (int i = 0; i < n; i++)
{
total += arr[i];
}
return total;
}
1. 函数如何使用指针来处理数组
在一般情况下,将数组名视为指针,将数组名解释为第一个元素的地址:
cookies = &cookies[0] //array name is address of first element
上述程序执行下面的函数调用:
int sum = sum_arr(cookies,ArSize);
其中,cookies是数组名,cookies是其第一个元素的地址,因此函数传递的是地址。由于数组的元素的类型为int,因此cookies的类型必须是int指针,即int*。这表明函数头应该是这样:
int sum = sum_arr(int * arr, int n) //array = array name, n = size
其中用int * arr替换了int arr [ ]。这证明了这两个函数头是正确的,在C++中,当用于函数头或函数原型中,int *arr和int arr[ ]的含义才相同,在其他上下文中,int * arr和int arr[ ]的含义并不相同。无论arr是指针还是数组名,表达式arr[3]都指数组的第四个元素,就目前而言,记住下面的两个恒等式:
arr[i] == *(ar + i); //value in two natations
&arr[i] == ar+i; //address in two natations
切记,将指针(包括数组名)加1,实际上是加了一个与指针指向的类型的长度(以字节为单位)相等的值。
2. 将数组作为参数意味着什么
函数调用sum_arr(cookies,AeSize)将cookies数组第一个元素的地址和数组中的元素在数目传递给sum_arr()函数将cookies的地址赋给指针变量arr,将ArSize赋给int变量n。这意味着程序并没有将数组内容传递给函数,而是将数组的地址、包含的元素种类以及元素数目提交给函数。有了这些信息之后,函数便可以使用原来的数组,传递常规变量时,函数将使用该变量的拷贝;但传递数组时,函数将使用原来的数组。实际上,这种区别并不违背C++按值传递的方法,sum_arr()函数仍传递了一个值,这个值背负给了一个新变量,但是这个值是一个地址,而不是数组的内容。