建设银行网站多少,静态网站建设开发,上海浦东人力资源公共招聘网,网站建设wangzhii当用数组名作函数参数时#xff0c;如果形参数组中各元素的值发生变化#xff0c;实参数组元素的值随之变化。
1.数组元素做实参的情况#xff1a;
如果已经定义一个函数#xff0c;其原型为
void swap(int x,int y);假设函数的作用是将两个形参#xff08;x,y#xf…当用数组名作函数参数时如果形参数组中各元素的值发生变化实参数组元素的值随之变化。
1.数组元素做实参的情况
如果已经定义一个函数其原型为
void swap(int x,int y);假设函数的作用是将两个形参x,y进行交换现在有以下的函数调用
swap (a[0],a[1]);用数组元素做实参的情况与用变量作实参的情况一样是“值传递”方式将a[0]和a[1]的值单向传递给x和y。当x和y的值改变时a[0]和a[1]的值并不改变。
2.数组名作函数形参的情况
实参数组名代表该数组首元素的地址而形参是用来接收从实参传递过来的数组首元素的地址的。因此形参应该是一个指针变量只有指针变量才能存放地址。实际上C编译都是将形参数组名作为指针变量来处理的。
例如定义一个函数funfun函数的形参写成数组的形式
void fun(int arr[],int n);但在程序编译时是将arr按指针变量来处理的相当于函数fun应写成
void fun(int *arr,int n);在该函数被调用时系统会在fun函数中建立一个指针变量arr用来存放从主调函数传递过来的实参数组元素的地址。如果在fun函数中用运算符sizeof测定arr所占字节数可以发现sizeof(arr)的值为4。这就证明了系统是把arr作为指针变量来处理的。例如
void fun(int arr[], int n)
{int s sizeof(arr);printf(arr所占字节数为%d\n, s);
}
int main()
{int brr[10];fun(brr, 10);return 0;}运行结果 当arr接收了实参数组的首元素地址后arr就指向实参数组的首元素也就是指向了brr[0]。因此arr就是brr[0]。arr1指向brr[1]arr2指向brr[2]arr3指向brr[3].也就是说*(arr1)*(arr2)*(arr3)分别是brr[1]brr[2]brr[3]。*(arri)和arr[i]是无条件等价的。因此在调用函数期间arr[0]和arr以及brr[0]都代表数组brr序号为0的元素。
【注意】
实参数组名代表一个固定的地址或者说是指针常量但形参数组名并不是一个固定的地址而是按指针变量处理。
在函数调用进行虚实结合后形参的值就是实参数组首元素的地址。在函数指向期间它可以在被赋值。
【例】定义一个数组名作形参的函数通过调用这个函数改变实参数组的值
int fun(int arr[], int n)
{//int s sizeof(arr);//printf(arr所占字节数为%d\n, s);int t;t arr[1];arr[1] arr[2];arr[2] t;return arr[0];
}
int main()
{int brr[10] { 1,3,2,4,5,6,7,8,9,10 };fun(brr, 10);for (int i 0; i 10; i){printf(%d , brr[i]);}return 0;}运行结果 常用这种方法通过调用一个函数来改变实参数组的值。
3.变量名做函数参数和用数组名做函数参数的比较
1当实参类型是变量名时要求形参的类型也是变量名通过形参传递的信息是变量的值通过函数调用不能改变实参变量的值。
2当实参类型是数组名时要求形参的类型是数组名或者指针变量通过形参传递的信息是实参数组首元素的地址通过函数调用能改变实参变量的值。
说明C语言调用函数时虚实结合的方法都是采用“值传递”方式当用变量名作为函数参数时传递的是变量的值。当用数组名作函数参数时由于数组名代表的是数组首元素地址因此传递的值是地址所以要求形参为指针变量。
4.数组名和指针变量作为函数的形参
在C语言中用下标法和指针法都可以访问一个数组如果有一个数组a则a[i]和*(ai)无条件等价。用数组名作形参以便于实参数组对应比较直观便于理解。从应用的角度看用户可以认为有一个形参数组它从实参数组那里得到起始地址因此形参数组与实参数组共占同一段内存单元在调用函数期间如果改变了形参数组的值也就是改变了实参数组的值。在主调函数中就可以利用这些已经改变的值。
【例】将数组a中n个整数按相反顺序存放用一个函数inv来实现交换。实参用数组名a形参可用数组名也可用指针变量。
void inv(int x[], int n)//形参x是数组名
{int temp;int m (n - 1) / 2;for (int i 0; i m; i){int j n - 1 - i;//把x[i]和x[j]交换temp x[i];x[i] x[j];x[j] temp;}return;
}
int main()
{int a[10] { 1,2,3,4,5,6,7,8,9,10 };inv(a, 10);//调用inv函数进行交换for (int i 0; i 10; i){printf(%d , a[i]);}
}运行结果 结果分析 在main主函数中定义整型数组a并赋初值。函数inv的形参数组名为x。在定义inv函数时可以不指定形参数组x的大小元素个数。因为形参数组名实际上是一个指针变量并不是真的开辟一个数组空间定义实参数组时必须指定数组大小因为要开辟相应的存储空间。inv函数的形参n用来接收需要处理的元素的个数。在main函数中有函数调用语句inv(a,10);表示要求将a数组的10个元素颠倒排列。如果改为inv(a,5);则表示要求将a数组的前5个元素颠倒排列此时函数inv只处理5个数组元素。函数inv中的m是i值得上限当im时循环继续执行当im时则结束循环过程。
改写代码将函数inv中得形参x改成指针变量
void inv(int *x, int n)
{int temp;//定义一个中间变量用来交换两个变量得值int m (n - 1) / 2;int* p;//定义一个指针变量pp x m;//p指向a[m]元素的地址int* i;//定义一个指针变量ii x;//i指向数组首元素的地址int* j;//定义一个指针变量jj x n - 1;//j指向数组最后一个元素的地址for (ix;ip;i,j--){//交换i和j所指向的数组元素的值temp *i;*i *j;*j temp;}return;
}
int main()
{int a[10] { 1,2,3,4,5,6,7,8,9,10 };inv(a, 10);for (int i 0; i 10; i){printf(%d , a[i]);}
}改写后函数inv中得形参有数组名x[]变为了指针变量*x相应的实参仍是数组名a即数组a首元素的地址将它传给形参指针变量x这时x就指向a[0]。xm是a[m]元素得地址。设i和j以及p都是指针变量用它们指向有关元素。交换i和j所指向的数组元素的值实际上就是交换a[i]和a[j]的值。
运行结果
5.归纳分析
1形参和实参都用数组名
int fun(int x[],int n)
{...
}
int main()
{int a[10];...fun(a,10);...return 0;
}由于形参数组名x接收了实参数组名首元素a[0]的地址因此可以认为在函数调用期间形参数组和实参数组共用一段内存单元如图所示
2实参用作数组名形参用指针变量
void fun(int *x,int n)
{...
}
int main()
{int a[10];...fun(a,10);...return 0;
}实参a为数组名形参x为int *型的指针变量调用函数开始后形参x指向a[0]即xa[0]通过x值的改变可以指向a数组的任一元素如图所示
3实参形参都用指针变量
void fun(int *x,int n)
{...
}
int main()
{int a[10];int *pa;...fun(a,10)...return 0;
}实参p和形参x都是int*型指针变量。先使用实参指针变量p指向数组元素a[0]p的值是a[0]。然后将p的值传给形参变量xx的初始值也是a[0]通过x的值的改变可以使x指向数组a的任一元素如图所示
4实参为指针变量形参为数组名
void fun(int x[],int n)
{...
}
int main()
{int a[10];int *pa;...fun(p,10);...return 0;
}实参p作为指针变量它指向a[0]。形参为数组名x编译系统把x作为指针变量处理将a[0]的地址传给形参x使x也指向a[0]。也可以理解为形参数组x和a数组共用同一内存单元在函数执行过程中可以使x[i]的值发生变化而x[i]就是a[i]。这样主函数可以使用改变了的数组元素值如图所示 【例】指针变量做实参
void inv(int* x, int n)
{int temp;int m (n - 1) / 2;int* p;p x m;int* i;i x;int* j;j x n - 1;for (i x; i p; i, j--){temp *i;*i *j;*j temp;}return;
}
int main()
{int a[10];int* p a;//指针变量p指向a[0]//输入数组a的元素for (int i 0; i 10; i, p){scanf(%d, p);}p a;//将指针变量p重新指向a[0]inv(p, 10);//调用inv函数实参是变量pfor (int i 0; i 10; i){printf(%d , a[i]);}return 0;
}运行结果 上面的main函数中的指针变量p是有确定值的。如果在main函数中不设数组只设指针变量就会出错。假如把主函数修改如下
void inv(int* x, int n)
{int temp;int m (n - 1) / 2;int* p;p x m;int* i;i x;int* j;j x n - 1;for (i x; i p; i, j--){temp *i;*i *j;*j temp;}return;
}
int main()
{int a[10];int* p;//输入数组a的元素for (int i 0; i 10; i){scanf(%d, pi);}inv(p, 10);//调用inv函数实参是变量pfor (int i 0; i 10; i){printf(%d , *(pi));}return 0;
}
编译时会出错原因是指针变量p没有确定值谈不上指向哪个变量 因此下面这样的使用是不正确的
void fun(int x[],int n)
{...
}
int main()
{int *p;...fun(p,10);
}【注意】如果指针变量做实参必须先使指针变量有确定的值指向一个已经定义的对象。
以上4种方法实质上都是地址的传递。其中3和4两种只是形式上不同实际上形参都是使用的指针变量。
【例】使用指针方法对10个整数按由大到小的顺序排列。 【思路】在主函数种定义数组a存放10个整数定义int*型指针变量p指向a[0]。定义函数sort使数组a种的元素由大到小的顺序排列。在主函数中调用sort函数用指针变量p作实参。sort函数的形参用数组名。用选择法进行排序。
//定义sort函数x是形参数组名
void sort(int x[], int n)
{int temp;for (int i 0; i n-1; i){for (int j i 1; j n; j){if (x[j]x[i]){temp x[i];x[i] x[j];x[j] temp;}}}
}
int main()
{int a[10];int* p a;//指针变量p指向a[0]//输入10个整数for (int i 0; i 10; i){scanf(%d, p);}p a;//指针变量p重新指向a[0]sort(p, 10);//调用sort函数//输出排序后的10个数组元素for (int i 0; i 10; i){printf(%d , *p);p;}return 0;
}运行结果 如果sort函数中将x定义为指针变量在函数中仍可以用x[i]和x[j]这样的形式表示数组元素它就是xi和xj所指的数组元素。