Pointers on C——8 Arrays.9

来源:互联网 发布:ps下载mac免费版下载 编辑:程序博客网 时间:2024/05/22 02:24

8.1.6 Array Names as Function Arguments

What happens when an array name is passed as an argument to a function? You now know that the value of an array name is a pointer to the first element of the array, so it makes sense that a copy of this pointer value is passed to the function. A subscript used in the function will perform indirection on this pointer, and it is through this indirection that the function can access or modify the elements of the calling programʹs array.

当一个数组名作为参数传递给一个函数时会发生什么情况呢?你现在已经知道数组名的值就是一个指向数组第1 个元素的指针,所以很容易明白此时传递给函数的是一份该指针的拷贝。函数如果执行了下标引用,实际上是对这个指针执行间接访问操作,并且通过这种间接访问,函数可以访问和修改调用程序的数组元素。


Now I can explain the apparent contradiction about argument passing in C. I stated earlier that all arguments to functions are passed by value but that arrays behave as though they were passed by reference. Call by reference is implemented by passing a pointer to the desired argument and then using indirection in the function to access the data through the pointer. The array name is a pointer, and subscripts perform indirection.

现在我可以解释C 关于参数传递的表面上的矛盾之处。我早先曾说过所有传递给函数的参数都是通过传值方式进行的,但数组名参数的行为却仿佛它是通过传址调用传递的。传址调用是通过传递一个指向所需元素的指针,然后在函数中对该指针执行间接访问操作实现对数据的访问。作为参数的数组名是个指针,下标引用实际执行的就是间接访问。


So where is the call‐by‐value behavior with arrays? The function is passed a copy of the argument (a copy of the pointer to the beginning of the array) so the function is free to manipulate its pointer parameter without fear of modifying the corresponding argumentʹs value.

那么数组的传值调用行为又是表现在什么地方呢?传递给函数的是参数的一份拷贝(指向数组起始位置的指针的拷贝),所以函数可以自由地操作它的指针形参,而不必担心会修改对应的作为实参的指针。


So there is no contradiction after all: all arguments are passed by value. Of course, when you pass a pointer to a variable and the function uses indirection on the pointer, the function can modify the variable. Though it was not obvious at first glance, this process occurs with array name arguments. The argument, a pointer, is actually passed by value, and the function gets a copy of the pointer, which can be modified without fear of changing the callerʹs argument.

所以,此处并不存在矛盾:所有的参数都是通过传值方式传递的。当然,如果你传递了一个指向某个变量的指针,而函数对该指针执行了间接访问操作,那么函数就可以修改那个变量。尽管初看上去并不明显,但数组名作为参数时所发生的正是这种情况。这个参数(指针)实际上是通过传值方式传递的,函数得到的是该指针的一份拷贝,它可以被修改,但调用程序所传递的实参并不受影响。


Program 8.1 is a simple function that illustrates these points. It copies the string contained in the second argument to the buffer to which the first argument points.The callerʹs buffer is modified because of the indirection, yet the arguments (the pointers) are modified without changing the callerʹs pointer arguments.

程序8.1 是一个简单的函数,用于说明这些观点。它把第2 个参数中的字符串复制到第1 个参数所指向的缓冲区。调用程序的缓冲区将被修改,因为函数对参数执行了间接访问操作。但是,无论函数对参数(指针)如何进行修改,都不会修改调用程序的指针实参本身(但可能修改它所指向的内容)。


Note the expression *string++ in the while statement. It fetches the character to which string points and, as a side effect, modifies string to point to the next character. Changing the parameter in this way does not affect the argument in the calling program, because only the functionʹs copy is changed.

注意while 语句中的*string++表达式。它取得string 所指向的那个字符,并且产生一个副作用,就是修改string,使它指向下一个字符。用这种方式修改形参并不会影响调用程序的实参,因为只有传递给函数的那份拷贝进行了修改。

/*

** Copy the string contained in the second argument to the

** buffer specified by the first argument.

*/

void

strcpy( char *buffer, char const *string )

{

/*

** Copy characters until a NUL byte is copied.

*/

while( (*buffer++ = *string++) != '\0' )

;

}

Program 8.1 String copy


There are two other points about this function that are worth mentioning (or reiterating). First, the parameter is declared as a pointer to const characters. Why is this declaration important for a function that is not going to modify the characters in the first place? There are at least three reasons. First, it is good documentation.Someone wishing to use this function can see from the prototype that the data will not be changed, without reading the code (which might not be available). Second, the compiler will be able to catch any programming error that causes accidental modification. Lastly, the declaration allows const arguments to be passed to the function.

关于这个函数,还有两个要点值得一提(或强调)。首先,形参被声明为一个指向const 字符的指针。对于一个并不打算修改这些字符的函数而言,预先把它声明为常量有何重要意义呢?这里至少有三个理由。第一,这是一样良好的文档习惯。有些人希望仅观察该函数的原型就能发现该数据不会被修改,而不必阅读完整的函数定义(读者可能无法看到)。第二,编译器可以捕捉到任何试图修改该数据的意外错误。第三,这类声明允许向函数传递const 参数。


The second point to be made about this function is the declaration of the argument and the local variable as register variables. On many machines register variables will result in code that executes faster than if they were in static memory or on the stack, as illustrated earlier with the array copy functions. Runtime efficiency is especially important with a function such as this one, which is likely to be called quite often because it performs such a useful task.

关于这个函数的第2 个要点是函数的参数和局部变量被声明为register 变量。在许多机器上,register 变量所产生的代码将比静态内存中的变量和堆栈中的变量所产生的代码执行速度更快。这一点在早先讨论数组复制函数时就已经提到。对于这类函数,运行时效率尤其重要。它被调用的次数可能相当多,因为它所执行的是项极为有用的任务。


However, it depends on your environment whether using register variables will result in an improvement. Many current compilers can do a better job of register allocation than the programmer. With such a compiler, using register declarations can actually cause a decrease in efficiency. Check the documentation that comes with your compiler to see if it performs its own register allocation.

但是,这取决于在你的环境中,使用register 变量是否能够产生更快的代码。许多当前的编译器比程序员更加懂得怎样合理分配寄存器。对于这类编译器,在程序中使用register 声明反而可能降低效率。请检查一下你的编译器的有关文档,看看它是否执行自己的寄存器分配策略。


上一章 Pointers on C——8 Arrays.8

原创粉丝点击