作为函数参数的数组名

当一个数组名作为参数传递给一个函数时会发生什么情况呢?

已知:数组名的值 == 指向数组第一个元素的指针。

此时,传递给函数的,是一份该指针的copy(这里注意,后面讲解)。函数如果执行了下标引用,实际上是对这个指针执行了间接访问操作,并且通过这种这种间接访问,函数可以访问和修改调用程序的数组元素。

说明:

所有传递给函数的参数都是通过“传值”方式进行的,但是数组名参数的行为却仿佛是通过“传址”调用传递的。

“传址”调用是通过传递一个指向所需元素的指针,然后在函数中队该指针执行间接访问操作实现对数据的访问。

其实,作为函数参数的数组名,传递的只是参数的一份copy,也是“传值”的方式。所以,函数参数的数组名可以进行自由的操作,而不会修改对应的作为实参的指针。

这里说明一点,作为数组名 == 一个指针常量。(是不允许修改的。呵呵)

 

问题:

如果你想把一个数组名参数传递给函数,正确的函数形式应该是怎样的?

他是应该声明为一个个指针还是一个数组?

我们现在知道,调用函数时实际传递的是一个指针,所以函数的形参实际上是个指针。但为了使程序员新手更容易上手一些,编译器也接受数组形式函数参数,因此,下面两个函数原型是相等的:

int str(char *string);

int str(char string[]);

这个相等性暗示指针和数组名实际上是相等的,也就是说对于数组形参,你可以使用任何一种形式的声明。

你可以使用任何一种声明,但这两种声明更精确?答案是:指针。因为实参实际上是个指针,而不是数组。同样,表达式:

sizeof(string)的值是指向字符的指针的长度,而不是数组的长度。

 

现在,我们清楚了为什么函数原型中的一维数组形参无需写明他的元素数目,因为函数并不为数组参数分配内存空间。形参值是一个指针,他指向的是已经在其他地方分配好内存的空间。

另外,这种方式使函数无法知道数组的长度。如果函数需要知道数组的长度,他必须作为一个显式的参数传递给函数。

 

多维数组:一样,实际传递的是个指向数组第一个元素的指针。但是,和一维的区别,多维数组的每个元素本身是另外一个数组,编译器需要知道他的维数,以便为函数形参的下标表达式进行求值。

例子:

int vector[10];

...

func_1(vector);

参数vector的类型是指向整型的指针,所以func_1的原型,可以是下面2种中任何一种:

void func_1(int *vec);

void func_1(int vec[]);

作用于vec上面的指针运算把整型的长度作为他的调整因子。

现在看一个矩阵:

int  matrix[3][10];

...

func_2(matrix);

这里,参数matrix的类型是指向包含10个整型元素的数组指针。func_2的原型是怎样的呢?你可以使用下面两种形式的任何一种:

void func_2(int (*mat)[10]);

void func_2(int mat[][10]);

在这个函数中,mat的第1个下标根据包含10个元素的整型数组的长度进行调整,接着第2个下标根据整形的长度进行调整,这和原先的matrix数组一样。

关键:在于编译器必须知道第2个及以后各维德长度才能对下标进行求值,因此在原型中必须声明这些维德长度。第1维德长度并不需要,因为在计算下标值时用不到他。

注意:在编写一维数组形参的函数原型时,既可以用数组形式,也可以把他写成指针形式。但是,多维数组,只有第1维可以进行如此选择。尤其是,把func_2写成下面的原型是错误的:

void func_2(int **mat);

这个例子,把mat声明为一个指向整型指针的指针,他和指向整型数组的指针并不是一回事。

 

就到这里,休息一下。呵呵

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值