C语言中的多态数据结构/函数调用
所有C程序都包含函数调用。例如,在最简单的“Hello World”程序中,使用了一个函数调用
#include <stdio.h>
int main( int argc , char *argv[] ) {
printf( "Hello, world.\n" ) ;
return 0 ;
}
函数printf()以字符串“Hello, world.\n”作为参数,并将文本作为结果显示在屏幕上。
当调用函数时,会为该函数的局部变量分配内存空间,并将参数的值复制并放置到函数的内存空间中。这就是为什么C语言有时被称为“按值调用”语言的原因。一个简单的检验这个原理的方法是使用一个名为“No Swap”的程序。
#include <stdio.h>
void noswap( int x , int y ) ;
int main( int argc , char *argv[] ) {
int x , y ;
x = 5 ;
y = 9 ;
printf( "The values of x and y are %d and %d before the function noswap.\n" , x , y ) ;
noswap( x , y ) ;
printf( "The values of x and y are %d and %d after the function noswap.\n" , x , y ) ;
return 0 ;
}
void noswap( int x , int y ) {
int temp ;
temp = x ;
x = y ;
y = temp ;
}
该程序的输出将是
The values of x and y are 5 and 9 before the function noswap.
The values of x and y are 5 and 9 after the function noswap.
该程序的目的是交换x和y的值,但显然情况并非如此。这是因为实际的变量x和y没有传递给函数noswap(),而是复制了变量的值并推入函数的运行时堆栈。可以通过操作这种行为以及给定函数的返回值来创建瞬时处理的错觉。以下代码是一个简单的加法程序,它演示了将两个整数加在一起的能力。
#include <stdio.h>
int add( int x , int y ) ;
int main( int argc , char *argv[] ) {
int x , y ;
printf( "Please enter two integers to be added together: " ) ;
scanf( "%d %d" , &x , &y ) ;
printf( "The sum of %d and %d is %d.\n" , x , y , add( x , y ) ) ;
return 0 ;
}
int add( int x , int y ) {
return ( x + y ) ;
}
尝试编辑add()函数使其进行减法、乘法或求幂运算(在不添加其他C库的情况下最难),而不是加法。
C语言中的所有类型都可以按值传递,包括结构体、联合体和数组。
使用指针作为参数是修改除声明它的函数之外的函数中局部变量的唯一方法。使用指针作为参数是一种被称为“模拟按引用调用”的方法。它的用法相当简单:程序不是传递变量值的副本,而是简单地传递指向调用函数中实际值的指针。因此,必须在被调用函数中对变量进行解引用。让我们再次研究“No Swap”,但现在它将被称为“Swap”。
#include <stdio.h>
void swap( int *x , int *y ) ;
int main( int argc , char *argv[] ) {
int x , y ;
x = 5 ;
y = 9 ;
printf( "The values of x and y are %d and %d before the function swap.\n" , x , y ) ;
swap( &x , &y ) ;
printf( "The values of x and y are %d and %d after the function swap.\n" , x , y ) ;
return 0 ;
}
void swap( int *x , int *y ) {
int temp ;
temp = *x ;
*x = *y ;
*y = temp ;
}
该程序的输出将是
The values of x and y are 5 and 9 before the function noswap.
The values of x and y are 9 and 5 after the function noswap.
请注意,当调用swap()时,使用了取地址运算符 (&)。这是因为x和y都不是指针。在变量名后附加取地址运算符会导致传递变量的指针而不是副本。由于指针只是指向变量地址的引用,因此会创建一个指针的副本并传递给函数,这就是为什么这种方法只是模拟按引用调用,而不是真正的按引用调用。
数组的处理方式与其他变量不同。这是因为它们的名称(没有下标 [] 来表示特定值)只是一个指向数组第一个项目的指针。因此,A 和 &A[0] 相同。此外,像 *A 这样的解引用将返回 A[0] 的值。
由于这种行为,将数组传递给函数并修改它们非常容易。
#include <stdio.h>
void array_copy( int *A , int *B ) ;
int main( int argc , char *argv[] ) {
int i ;
int array[5] ;
int other_array[5] ;
printf( "Please enter five numbers, separated by a space: " ) ;
for ( i = 0 ; i < 5 ; i++ ) scanf( "%d" , &array[i] ) ;
for ( i = 0 ; i < 5 ; i++ ) printf( "%d " , array[i] ) ;
printf( "\n" ) ;
array_copy( array , other_array ) ;
for ( i = 0 ; i < 5 ; i++ ) printf( "%d " , other_array[i] ) ;
printf( "\n" ) ;
return 0 ;
}
void array_copy( int *A , int *B ) {
int i ;
for ( i = 0 ; i < 5 ; i++ ) B[i] = A[i] ;
}
请注意,即使在调用array_copy()时没有使用取地址运算符,两行的输出也是相同的。这是因为数组基址已经是指针。