为什么C语言把数组形参当做指针
之所以要把传递给函数的数组参数转换为指针,是出于效率的考虑,这个理由常常也是为违反软件工程做法的一种解释。全面的语义检查被可移植的C编译器所排斥,其理由很牵强,它们认为把lint程序作为一个单独的程序,“效率”会高一些。
在C语言中,所有非数组形式的数据实参均以传值形式(对实参制作一份副本并传递给调用的函数,函数不能修改作为实参的实际变量的值,而只能修改传递给它的那份副本)调用。然而,如果要赋值整个数组,无论在时间上还是在内存空间上的开销都可能是非常大的。而且在绝大多数情况下,你其实并不需要整个数组的副本,而只想告诉函数在那一时刻对那个特定的数组感兴趣。要达到这个目的,可以考虑的方法是在形参上增加一个存储说明符(storage specifier),它表示它是传值调用还是传址调用。Pascal语言就是这么做的。如果采用“所有的数组在作为参数传递时都传换为指向数组起始地址的指针,而其他的函数均采用传值调用”的约定,就可以简化编译器。类似地,函数的返回值绝不能是一个函数数组,而只能是指向数组或函数的指针。
事实上,取地址操作符的主要用途就是实现传址调用。“传址调用”这个说法从严格意义上说并不十分准确,因为编译器的机制非常清楚---在被调用的函数中,你只拥有一个指向变量的指针而不是变量本身。如果你取实参的地址或对它进行复制,就能体会到两者的差别。
数组形参是如何被引用的
下标形式的数组进行访问所需要的几个步骤。
func(char p[]) ... c = p[i];
func(char *p) ... c = p[i];
编译器符号表显示p可以取址,从