C语言中参数的传值问题
C语言中函数参数传递
C语⾔中函数参数传递C语⾔中函数参数传递的三种⽅式(1)值传递,就是把你的变量的值传递给函数的形式参数,实际就是⽤变量的值来新⽣成⼀个形式参数,因⽽在函数⾥对形参的改变不会影响到函数外的变量的值。
(2)地址传递,就是把变量的地址赋给函数⾥形式参数的指针,使指针指向真实的变量的地址,因为对指针所指地址的内容的改变能反映到函数外,能改变函数外的变量的值。
(3)引⽤传递,实际是通过指针来实现的,能达到使⽤的效果如传址,可是使⽤⽅式如传值。
说⼏点建议:如果传值的话,会⽣成新的对象,花费时间和空间,⽽在退出函数的时候,⼜会销毁该对象,花费时间和空间。
因⽽如果int,char等固有类型,⽽是你⾃⼰定义的类或结构等,都建议传指针或引⽤,因为他们不会创建新的对象。
例1:下⾯这段代码的输出结果为:#include<stdio.h>void change(int*a, int&b, int c){c=*a;b=30;*a=20;}int main ( ){int a=10, b=20, c=30;change(&a,b,c);printf(“%d,%d,%d,”,a,b,c);return 0;}结果:20 30 30解析:1,指针传参 -> 将变量的地址直接传⼊函数,函数中可以对其值进⾏修改。
2,引⽤传参 -> 将变量的引⽤传⼊函数,效果和指针相同,同样函数中可以对其值进⾏修改。
3,值传参 -> 在传参过程中,⾸先将c的值复制给函数c变量,然后在函数中修改的即是函数的c变量,然后函数返回时,系统⾃动释放变量c。
⽽对main函数的c没有影响。
例2:#include<stdio.h>void myswap(int x, int y){int t;t=x;x=y;y=t;}int main(){int a, b;printf("请输⼊待交换的两个整数:");scanf("%d %d", &a, &b);myswap(a,b); //作为对⽐,直接交换两个整数,显然不⾏printf("调⽤交换函数后的结果是:%d 和 %d\n", a, b);return 0;}#include<stdio.h>void myswap(int *p1, int *p2){int t;t=*p1;*p1=*p2;*p2=t;}int main(){int a, b;printf("请输⼊待交换的两个整数:");scanf("%d %d", &a, &b);myswap(&a,&b); //交换两个整数的地址printf("调⽤交换函数后的结果是:%d 和 %d\n", a, b);return 0;}#include<stdio.h>void myswap(int &x, int &y){int t;t=x;x=y;y=t;}int main(){int a, b;printf("请输⼊待交换的两个整数:");scanf("%d %d", &a, &b);myswap(a,b); //直接以变量a和b作为实参交换printf("调⽤交换函数后的结果是:%d 和 %d\n", a, b);return 0;}第⼀个的运⾏结果:输⼊2 3,输出2 3第⼆个的运⾏结果:输⼊2 3,输出3 2第三个的运⾏结果:输⼊2 3,输出3 2解析:在第⼀个程序中,传值不成功的原因是指在形参上改变了数值,没有在实参上改变数值。
c语言进程间参数传递
c语言进程间参数传递C语言是一种广泛应用于系统编程的高级编程语言,其提供了一些机制来实现进程间的参数传递。
进程间参数传递是指在多个进程之间传递数据或信息,使得不同进程能够相互通信和共享数据。
本文将介绍C语言中几种常见的进程间参数传递的方式。
一、命令行参数传递在C语言中,可以通过命令行参数传递参数给一个进程。
命令行参数是在运行程序时通过命令行输入的参数,可以在程序内部进行处理。
例如,可以通过命令行参数传递文件名、选项等信息给程序。
命令行参数是以字符串数组的形式传递给main函数的,它的原型为:int main(int argc, char *argv[])其中,argc表示命令行参数的个数,包括程序本身的名称;argv是一个指针数组,指向每个命令行参数的字符串。
通过命令行参数传递参数的示例代码如下:```c#include <stdio.h>int main(int argc, char *argv[]) {int i;printf("argc = %d\n", argc);for (i = 0; i < argc; i++) {printf("argv[%d] = %s\n", i, argv[i]);}return 0;}```运行该程序并输入命令行参数,可以看到程序会打印出命令行参数的个数和每个参数的值。
二、环境变量传递环境变量是一种全局变量,用来存储系统的配置信息或者用户的偏好设置。
在C语言中,可以通过环境变量传递参数给一个进程。
C语言提供了一个全局变量environ,它是一个指向环境变量字符串数组的指针。
通过遍历environ数组,就可以获取到所有的环境变量及其对应的值。
通过环境变量传递参数的示例代码如下:```c#include <stdio.h>extern char **environ;int main() {int i;for (i = 0; environ[i] != NULL; i++) {printf("environ[%d] = %s\n", i, environ[i]);}return 0;}```运行该程序,可以看到程序会打印出所有的环境变量及其对应的值。
c函数数组参数传递
c函数数组参数传递一、函数数组参数传递的基本概念在C语言中,函数数组参数传递是一种常见的方式。
它可以将数组作为参数传递给函数,在函数内部对数组进行操作,并将结果返回给调用者。
这种方式可以提高程序的运行效率,减少代码量,也方便了程序的维护和修改。
二、C语言中函数数组参数传递的特点1. 数组名作为函数参数时,实际上是将数组首元素地址传递给了形参。
2. 数组作为函数参数时,可以改变数组元素的值。
3. 在函数内部对形参进行修改不会影响实参。
三、C语言中函数数组参数传递的方法1. 通过指针方式进行传递2. 通过下标方式进行传递3. 通过指针和下标混合方式进行传递四、通过指针方式进行传递1. 定义一个指向数组首元素的指针变量。
2. 将该指针变量作为形参,将实际的数组名作为实参。
3. 在函数内部使用该指针变量访问数组元素。
五、通过下标方式进行传递1. 将整个数组作为形参,将实际的数组名作为实参。
2. 在函数内部使用下标访问数组元素。
六、通过指针和下标混合方式进行传递1. 将指向数组首元素的指针变量和数组长度作为形参,将实际的数组名作为实参。
2. 在函数内部使用指针和下标访问数组元素。
七、C语言中函数数组参数传递的示例代码1. 通过指针方式进行传递void print_array(int *p, int n){int i;for(i=0;i<n;i++)printf("%d ",*(p+i));}int main(){int a[5] = {1,2,3,4,5};print_array(a,5);return 0;}2. 通过下标方式进行传递void print_array(int a[], int n) {int i;for(i=0;i<n;i++)printf("%d ",a[i]);}int main(){int a[5] = {1,2,3,4,5};print_array(a,5);return 0;}3. 通过指针和下标混合方式进行传递void print_array(int *p, int n){int i;for(i=0;i<n;i++)printf("%d ",*(p+i));}int main(){int a[5] = {1,2,3,4,5};print_array(&a[0],5);return 0;}八、C语言中函数数组参数传递的注意事项1. 在定义函数时,形参可以省略数组大小。
C语言教程十一函数参数的传递和值返回
C语言教程十一、函数参数的传递和值返回前面我们说的都是无参数无返回值的函数,实际程序中,我们经常使用到带参数有返回值的函数。
一、函数参数传递1.形式参数和实际参数函数的调用值把一些表达式作为参数传递给函数。
函数定义中的参数是形式参数,函数的调用者提供给函数的参数叫实际参数。
在函数调用之前,实际参数的值将被拷贝到这些形式参数中。
2.参数传递先看一个例子:void a(int); /*注意函数声明的形式*/main(){int num;scanf(%d,&num);a(num); /*注意调用形式*/}void a(int num_back) /*注意定义形式*/{printf(%d\n,num_back);}在主函数中,先定义一个变量,然后输入一个值,在a()这个函数中输出。
当程序运行a(num);这一步时,把num的值赋值给num_back,在运行程序过程中,把实际参数的值传给形式参数,这就是函数参数的传递。
形参和实参可能不只一个,如果多于一个时,函数声明、调用、定义的形式都要一一对应,不仅个数要对应,参数的数据类型也要对应。
void a(int,float);main(){int num1;float num2;scanf(%d,&num1);scanf(%f,&num2);a(num1,num2);}void a(int num1_back,float num2_back){printf(%d,%f\n,num1_back,num2_back);}上面的例子中,函数有两个参数,一个是整型,一个是浮点型,那么在声明、调用、定义的时候,不仅个数要一样,类型也要对应。
如果不对应,有可能使的编译错误,即使没错误,也有可能让数据传递过程中出现错误。
再看一个例子:void a(int);main(){int num;scanf(%d,&num);a(num);}void a(int num){printf(%d\n,num);}看上面的例子,形式参数和实际参数的标识符都是num,程序把实际参数num 的值传递给形式参数num。
c语言函数多个参数传递
c语言函数多个参数传递摘要:1.引言2.C 语言函数参数传递的方式3.多个参数的传递4.传递参数的注意事项5.结论正文:【引言】C 语言是一种广泛使用的编程语言,它具有简洁、高效的特点。
在C 语言程序设计中,函数的使用是必不可少的。
函数可以实现代码的模块化,使程序更加清晰易懂。
在函数调用时,参数的传递是一个重要的环节。
本篇文章主要介绍C 语言函数多个参数的传递方法及其注意事项。
【C 语言函数参数传递的方式】C 语言函数参数传递方式主要有两种:值传递和指针传递。
1.值传递:函数在调用时,会将实参的值复制到形参中。
这意味着形参和实参是两个独立的变量,它们之间互不影响。
值传递适用于基本数据类型,如int、float 等。
2.指针传递:函数在调用时,会将实参的地址传递给形参。
这意味着形参和实参共享同一内存空间,对形参的修改将影响实参。
指针传递适用于数组和结构体等复合数据类型。
【多个参数的传递】在实际编程中,函数可能需要接收多个参数。
C 语言中,多个参数的传递可以通过以下方式实现:1.按顺序传递:将多个参数按照声明的顺序依次传递给函数。
这种方式较为简单,但当参数较多时,容易出错。
2.使用数组:将多个参数封装在一个数组中,然后将数组作为参数传递给函数。
这种方式可以减少参数传递的错误,但需要注意数组的大小和类型。
3.使用结构体:将多个参数封装在一个结构体中,然后将结构体作为参数传递给函数。
这种方式可以方便地管理多个参数,同时具有较好的封装性。
【传递参数的注意事项】在函数参数传递过程中,需要注意以下几点:1.参数类型匹配:确保实参的类型与形参的类型匹配,否则会导致编译错误。
2.参数顺序正确:按照函数声明的顺序传递参数,否则会导致函数调用失败。
3.注意参数传递的方式:根据参数的类型选择合适的传递方式,避免因为传递方式不当导致的程序错误。
【结论】C 语言函数多个参数的传递是程序设计中常见的场景。
通过掌握不同的参数传递方式和注意事项,可以有效提高程序的编写效率和稳定性。
C语言关于结构体做参数传递
C语言关于结构体做参数传递C语言中结构体类型可以作为函数的参数进行传递。
通过结构体做参数传递,可以将一个或多个相关的数据封装到一个结构体中,然后直接传递结构体作为参数,从而简化函数调用过程,提高程序可读性和维护性。
在C语言中,结构体是一种用户自定义的数据类型,它由多个不同类型的成员组成。
结构体的声明通常放在函数外部,以便于多个函数共享同一种数据结构。
下面我们来探讨几种关于结构体做参数传递的常见使用方式以及它们的特点。
首先是结构体值传递。
结构体作为函数参数传递时,会将结构体的每个成员的值拷贝一份传递给函数参数,函数内部对参数进行的修改不会影响外部的原结构体。
下面是一个示例:```c#include <stdio.h>struct Personchar name[20];int age;};void displayPerson(struct Person p)printf("Name: %s\n", );printf("Age: %d\n", p.age);int maistruct Person p1 = {"Tom", 20};displayPerson(p1);return 0;```在这个示例中,displayPerson函数接受一个Person类型的参数p,并打印其成员name和age。
当displayPerson函数调用时,会将p1的值拷贝到参数p,所以在函数内部修改p的值不会影响p1的值。
输出结果为:```Name: TomAge: 20```其次是结构体指针传递。
结构体指针可以在函数内部直接修改结构体的值,从而实现对原结构体的修改。
下面是一个示例:```c#include <stdio.h>struct Pointint x;int y;};void movePoint(struct Point *p, int dx, int dy)p->x += dx;p->y += dy;int maistruct Point p = {1, 2};movePoint(&p, 3, 4);printf("New coordinates: (%d, %d)\n", p.x, p.y);return 0;```在这个示例中,movePoint函数接受一个Point类型的指针p,并将x和y成员分别增加dx和dy的值。
c语言函数参数传递方式
c语言函数参数传递方式C语言是一种广泛使用的编程语言,函数参数传递方式是C语言中非常重要的概念之一。
函数参数传递方式可以分为按值传递、按址传递和按引用传递三种方式。
本文将针对这三种方式进行详细讲解。
一、按值传递按值传递是指在函数调用时,将实际参数的值复制给形式参数,函数内部对形参的修改不会影响到实际参数的值。
这种方式适用于参数较少、参数值不需要在函数内部被修改的情况。
在按值传递的方式下,函数在栈内存中为形参分配空间,并将实参的值复制到形参中。
函数执行结束后,栈内存中的形参被销毁,不会影响到实参的值。
二、按址传递按址传递是指在函数调用时,将实际参数的地址传递给形式参数,函数内部通过指针对实参进行操作,可以修改实参的值。
这种方式适用于需要在函数内部修改实参值的情况。
在按址传递的方式下,函数在栈内存中为形参分配空间,并将实参的地址传递给形参。
函数内部通过指针对实参进行操作,修改实参的值。
由于传递的是地址,所以函数内部对形参的修改会影响到实参。
三、按引用传递按引用传递是C++中的特性,其本质是通过指针来实现的。
在C语言中,可以通过传递指针的方式来模拟按引用传递。
按引用传递的特点是可以修改实参的值,并且不需要像按址传递那样使用指针操作。
在按引用传递的方式下,函数在栈内存中为形参分配空间,并将实参的地址传递给形参。
函数内部通过引用的方式操作形参,可以直接修改实参的值。
由于传递的是地址,所以函数内部对形参的修改会影响到实参。
需要注意的是,按引用传递需要使用指针来实现。
在函数调用时,需要将实参的地址传递给形参,即传递一个指向实参的指针。
函数内部通过解引用指针来操作实参,可以达到修改实参的目的。
总结:C语言中的函数参数传递方式包括按值传递、按址传递和按引用传递三种方式。
按值传递适用于参数较少、参数值不需要在函数内部被修改的情况;按址传递适用于需要在函数内部修改实参值的情况;按引用传递需要使用指针来实现,通过传递实参的地址来实现对实参的修改。
C语言中函数参数传递问题探讨
数调用 中, 主调 函数通过 函数调用将实参中的数据传递 给被调
组元素 的值传送给形参 , 实现单 向的值传送。
vi npi o z (t ) d nv
{
函数的形参 , 从而实现 函数间 的数据传递。
2 形 参 和 实 参 的 特 点
量。
% 0 pif” d” ) r ( n ,;
() 2 实参可 以是常量 、 变量 、 表达式 、 函数等 , 无论 实参是何 种类型的量 , 在进行 函数调用时 , 它们都必须具有确定 的值 , 以 便把这些值 传送 给形参 。 ( ) 参和形参在数量 、 型、 3实 类 顺序 上应严格一致 , 否则会
递给形参 , 而不能 由形参传 回给实参 。
3s n( t i c ” l 】 &a ) npa z(i f
}
在 函数调用 时 , 数的传递有两 种形式 : 传递和地址传 参 值
递。
本程序实现的是判别 一个整数数组 中各元素的值 , 若大于 0 则输 出该值 , 若小于等于 0 则输 出0 值。首先定义一个无返 回 值 函数np 并说明其形参v z, 为整型变量 。 在函数体 中根据v 值输
数 名后 面括弧 中的参数 ( 或者 表达式 ) 为 “ 际参数 ” 简称 称 实 ( “ 实参 ” 。 )即形参 出现在函数定 义中 , 实参出现在主调函数 的函
互换后 的值 不能 回传给主调 函数 , 因此 , 主调 函数中的数值不
变。
示例二 : 数组元素作为 函数参数。 数组元素就是下标 变量 ,
递 的就是该数组的首地址 或者指针 的值 , 么形参接收到的是 那
c语言函数调用时参数传递方式的有哪几种,分别简述他们的传递方式
c语言函数调用时参数传递方式的有哪几种,分别简述他们的传
递方式
C语言函数调用时参数的传递方式主要有以下几种:
1. 值传递:函数调用时,将实际参数的值复制给形式参数,函数内部对形式参数进行修改不会影响实际参数的值。
这是最常见的参数传递方式。
2. 引用传递:通过传递变量的指针作为参数,函数内部可以直接通过指针访问和修改实际参数的值。
这种方式可以实现在函数内部改变实参的值。
3. 地址传递:传递变量的地址作为参数,在函数内部通过指针来访问和修改实际参数的值。
和引用传递类似,通过地址传递也可以改变实参的值。
4. 数组传递:将数组的首地址作为参数传递给函数,函数内部可以通过指针来访问和修改数组的元素。
5. 结构体传递:将整个结构体作为参数传递给函数,在函数内部可以直接访问和修改结构体中的成员。
需要注意的是,C语言中的参数传递都是按值传递的,包括引
用传递和地址传递。
所谓按值传递,是指在函数调用时将实参的值复制给形参,函数内部对形参的操作不会影响到实参的值。
但是通过引用传递和地址传递,可以通过指针来访问和修改实参的值,使得函数可以改变实参的值。
c++数组参数传递
c++数组参数传递C语言是一种面向过程的语言,它的基本数据类型较为直接,也使得它的程序逻辑更为直接明了。
在C语言中,参数的传递方式主要是通过值传递、指针传递和引用传递三种方式。
其中,数组作为C语言中的重要数据结构,其参数传递方式也是值得探讨的。
一、数组作为函数参数在C语言中,数组作为函数参数时,有两种传递方式:值传递和指针传递。
1. 值传递:将整个数组作为参数传递给函数,函数内部通过局部变量来接收该数组的值。
这种方式下,函数内部对数组的修改不会影响到原数组。
2. 指针传递:将数组的指针作为参数传递给函数,函数内部通过该指针来访问和修改数组。
这种方式下,函数内部对数组的修改会影响到原数组。
二、数组参数传递的优缺点1. 优点:通过指针传递数组参数,可以在函数内部直接操作数组,无需再通过拷贝的方式进行传递,可以减少内存占用和时间成本。
同时,这种方式也使得函数的参数更简洁,易于理解。
2. 缺点:值传递的方式可能会影响性能,因为将整个数组作为参数传递会给函数传递的时间和空间带来一定的负担。
而且,这种方式下如果对数组进行了修改,修改并不会影响到原数组,这可能会引起一些误解和误操作。
三、注意事项在C语言中,数组作为参数传递时,需要注意以下几点:1. 指针传递时,需要确保传递的指针指向的内存空间是有效的,否则可能会导致程序崩溃或数据错误。
2. 数组作为参数传递时,需要注意数组的大小和类型是否符合函数的声明要求,否则可能会导致编译错误或运行时错误。
3. 在函数内部对数组进行操作时,需要注意越界访问和非法修改等问题,避免导致数据错误或程序崩溃。
四、实际应用举例下面是一个使用指针传递数组参数的示例代码:```c#include <stdio.h>void printArray(int *arr, int size) {for (int i = 0; i < size; i++) {printf("%d ", arr[i]);}printf("\n");}int main() {int arr1[] = {1, 2, 3, 4, 5};int size = sizeof(arr1) / sizeof(arr1[0]);printArray(arr1, size); // 使用指针传递数组参数return 0;}```在这个示例中,`printArray`函数使用指针传递了`arr`和`size`两个参数。
c语言参数传递的两种方式
c语言参数传递的两种方式C语言是一种广泛应用于计算机编程的高级编程语言,它提供了多种参数传递的方式。
本文将介绍C语言中常用的两种参数传递方式:值传递和引用传递。
值传递是指将参数的值复制一份传递给函数。
在函数内部对参数的修改不会影响到原始变量的值。
这种方式适用于简单的数据类型,如整型、浮点型和字符型等。
下面是一个示例:```c#include <stdio.h>void changeValue(int num) {num = 10;}int main() {int num = 5;printf("Before change: %d\n", num);changeValue(num);printf("After change: %d\n", num);return 0;}```运行结果为:```Before change: 5After change: 5```可以看到,虽然在函数`changeValue`中将`num`的值修改为10,但是在`main`函数中打印`num`的值仍然是5。
这是因为在值传递中,函数内部对参数的修改只作用于参数的副本,不会影响到原始变量。
引用传递是指将参数的地址传递给函数,函数可以通过指针来访问和修改原始变量的值。
这种方式适用于复杂的数据类型,如数组和结构体等。
下面是一个示例:```c#include <stdio.h>void changeValue(int *num) {*num = 10;}int main() {int num = 5;printf("Before change: %d\n", num);changeValue(&num);printf("After change: %d\n", num);return 0;}```运行结果为:```Before change: 5After change: 10```可以看到,通过引用传递的方式,函数`changeValue`可以直接修改`num`的值。
C语言参数传递(值传递、地址传递)+二级指针
C语⾔参数传递(值传递、地址传递)+⼆级指针参数传递C语⾔参数传递⼀般分为:值传递和地址传递(本质上只有值传递)(注意:C语⾔中没有引⽤传递,C++才有引⽤传递,因为很多C语⾔环境是⽤C++编译器编译,使得C看起来⽀持引⽤传递,导致很多⽹上很多blog都把引⽤传递归为C语⾔参数传递的⼀类,当使⽤Microsoft Visual C++ 2010 Express或VC6之类的编译器时使⽤引⽤传递就⽆法编译通过)值传递:形参是实参的拷贝,改变形参的值并不会影响外部实参的值。
从被调⽤函数的⾓度来说,值传递是单向的(实参->形参)1 #include <stdio.h>23void swap(int x, int y);45 main()6 {7int a = 10, b = 20;89 swap(a, b);10 printf("a=%d\nb=%d\n", a, b);1112return0;13 }14void swap(int x, int y)15 {16int t;1718 t = x;19 x = y;20 y = t;21 }上述代码运⾏后a、b的值并未改变地址传递:形参为指向实参地址的指针,当对形参的指向操作时,就相当于对实参本⾝进⾏的操作1 #include <stdio.h>23void swap(int *x, int *y);45 main()6 {7int a = 10, b = 20;89 swap(&a, &b);10 printf("a=%d\nb=%d\n", a, b);1112return0;13 }14void swap(int *x, int *y)15 {16int t;1718 t = *x;19 *x = *y;20 *y = t;21 }上述代码执⾏后a和b值交换,a=20、b=10易错点补充:1 #include <stdio.h>23void swap(int *x, int *y);45 main()6 {7int a = 10, b = 20;8int *pp = &a;9int *kk = &b;10 swap(pp, kk);11 printf("a=%d\nb=%d\n", *pp, *kk);1213return0;14 }15void swap(int *x, int *y)16 {17int *t;1819 t = x;20 x = y;21 y = t;22 }请读者想⼀下,上述代码执⾏后a和b的值是否交换,为什么?上述代码看起来像交换了指针pp和kk的指向,实际上并没有代码的运⾏结果a=10、b=20,运⾏结果是a和b的值并没有改变,因为这时使⽤的实参pp,kk是值传递,传递的是指针的值,以指针pp来说,指针的值是变量a的地址,指针的值传⼊后⽤形参int *x和int *y接收,这⾥x和pp虽然都指向变量a的地址,但指针x和pp⾃⾝的地址并不相同(意思是x拷贝了⼀份pp的值),意味着你能改变变量a的值,但是不能改变pp的值(这⾥与值传递相似)为了更加直观,清晰的看出值的交换,这⾥添加⼀些代码来显⽰内存和变量的值1 #include <stdio.h>23void swap(int *x, int *y);45 main()6 {7int a = 10, b = 20;8int *pp = &a;9int *kk = &b;1011 printf("a的地址%p----b的地址%p\n\n", &a, &b);12 printf("pp的值%p----kk的值%p\n", pp, kk);13 printf("pp的地址%p----kk的地址%p\n\n", &pp, &kk);14 swap(pp, kk);15 printf("a = %d\nb = %d", *pp, *kk);1617return0;18 }19void swap(int *x, int *y)20 {21int *t;2223 printf("x的值%p----y的值%p\n", x, y);24 printf("x的地址%p----y的地址%p\n", &x, &y);26 t = x;27 x = y;28 y = t;29 }从pp和x的地址可以看出,x和pp是两块不同的内存区域,x在swap函数内执⾏完后并不会对pp值产⽣任何影响,相当于复制了⼀份pp的值,如下图(灵魂画⼿已上线)传⼊指针的值虽然不能对指针的值进⾏修改,但是可以通过地址直接对a的值进⾏修改也可以实现交换,代码如下1 #include <stdio.h>23void swap(int *x, int *y);45 main()6 {7int a = 10, b = 20;8int *pp = &a;9int *kk = &b;1011 swap(pp, kk);12 printf("a = %d\nb = %d", *pp, *kk);1314return0;15 }16void swap(int *x, int *y)17 {18int t;1920 t = *x;21 *x = *y;22 *y = t;23 }传⼊指针的值和和传⼊变量的地址在数值上是⼀样的,但是⼀个是传值传递⼀个地址传递,如下图(灵魂画⼿已经上线)⼆级指针上⾯提到的参数传递⽅式有,传⼊变量的值,传⼊变量的地址,传⼊指针的值三种参数传递⽅式下⾯介绍第四种,传⼊指针的地址,上⾯第⼆种(传⼊变量的地址)和第三种(传⼊指针的值)传递⽅式使⽤的⽤来接收参数的形参都是int *类型的指针这⾥因为传⼊的是指针的地址,所以要使⽤⼆级指针int **x,因为传⼊的指针的地址,实现值的交换的⽅式就有两种⼀种是直接对变量的值进⾏修改,另⼀种就是对指针的值进⾏修改第⼀种:直接对变量值进⾏修改1 #include <stdio.h>23void swap(int **x, int **y);45 main()6 {7int a = 10, b = 20;8int *pp = &a;9int *kk = &b;11 swap(&pp, &kk);12 printf("a = %d\nb = %d", *pp, *kk);1314return0;15 }16void swap(int **x, int **y)17 {18int t;1920 t = **x;21 **x = **y;22 **y = t;23 }第⼆种:对指针的值进⾏修改1 #include <stdio.h>23void swap(int **x, int **y);45 main()6 {7int a = 10, b = 20;8int *pp = &a;9int *kk = &b;1011 swap(&pp, &kk);12 printf("a = %d\nb = %d", *pp, *kk);1314return0;15 }16void swap(int **x, int **y)17 {18int *t;1920 t = *x;21 *x = *y;22 *y = t;23 }注意swap函数⾥⽤int *来交换指针的值,⽽不能⽤int **来进⾏交换,读者可⾃⾏修改代码验证想⼀下为什么?下⾯是⼆级指针⽰意图(灵魂画⼿已上线)若有疑问,欢迎留⾔。
c函数参数传递方式
c函数参数传递方式
C函数参数传递方式指的是在C语言中,将参数传递给函数的方式。
在C语言中,参数传递有以下几种方式:
1. 值传递(Pass by Value):将参数的值复制一份传递给函数,函数在调用过程中可以修改这些值,但不会影响原始参数的值。
这种方式是C语言中最常见的参数传递方式。
2. 引用传递(Pass by Reference):将参数的地址传递给函数,函数在调用过程中可以通过该地址修改原始参数的值。
这种方式可以避免复制大型数据结构的开销,但需要注意指针的使用。
3. 指针传递(Pass by Pointer):与引用传递类似,也是将参数的地址传递给函数。
但是和引用传递不同的是,指针可以被赋值为NULL,引用则不行。
使用指针传递需要注意指针的初始化和释放。
4. 数组传递(Pass by Array):将数组名作为参数传递给函数,函数在调用过程中可以访问数组的元素。
数组传递实际上是数组首元素的地址传递,因此可以看作是指针传递的一种特殊形式。
在C语言中,可以使用不同的参数传递方式来满足不同的需求。
在使用参数传
递时需要注意,不同的传递方式对内存使用和运行效率的影响是不同的,需要根据实际情况进行选择。
C语言教程十一函数参数的传递和值返回
C语言教程十一函数参数的传递和值返回函数参数的传递和值返回是C语言中非常重要的概念。
函数参数的传递指的是将数据传递给函数,并在函数内部进行处理和使用。
值返回指的是将函数内部的计算结果返回给调用函数的地方。
在C语言中,函数参数的传递有两种方式:按值传递和按引用传递。
按值传递是指将实际参数的值复制给形式参数,函数内部对形式参数进行的操作不会影响到实际参数。
这是C语言中最常见的函数参数传递方式。
例如:```c#include <stdio.h>void changeValue(int num)num = 10;int maiint num = 5;changeValue(num);printf("The value is: %d\n", num);return 0;```上述代码中,changeValue函数接收一个int类型的参数num,并在函数内部将num的值修改为10。
然而,在main函数中打印num的值时,输出结果仍然是5、这是因为changeValue函数中的num是main函数中num的一个副本,对副本的修改不会影响到原始变量。
按引用传递是指将实际参数的地址传递给形式参数,函数内部对形式参数的操作会直接影响到实际参数。
这种方式需要使用指针作为形式参数。
例如:```c#include <stdio.h>void changeValue(int *num)*num = 10;int maiint num = 5;changeValue(&num);printf("The value is: %d\n", num);return 0;```上述代码中,changeValue函数接收一个int指针类型的参数num,并在函数内部通过取值运算符*修改num指针所指向的值为10。
在main函数中打印num的值时,输出结果为10。
这是因为changeValue函数中的形式参数是main函数中num的地址,对地址上的值进行修改会直接影响到原始变量。
C语言函数参数传递问题
C语言函数参数传递问题C语言函数参数传递问题导语:在一些C语言教材和参考资料中,常常把函数参数传递分为“数值传递”和“地址传递”两种方式,这种概念模糊的分类方法给初学者的理解造成一定程度的困难。
下面就由店铺为大家介绍一下C语言函数参数传递问题,欢迎大家阅读!1概述函数是C语言程序的基本构成模块,通过使用函数,不仅可以省去重复代码的编写,还可以使程序更加模块化,从而有利于程序的阅读、修改和完善。
对于C语言的初学者来说,准确理解函数参数的传递方式是难点之一。
一些C语言程序设计教材[1][2]中把函数间的参数传递分为“数值传递”和“地址传递”两种方式,这种分类很容易使初学者混淆概念,更不能抓住参数传递的本质。
2传递方式和数据类型“值传递”是函数参数的唯一传递方式。
函数的参数分为实际参数(简称实参)和形式参数(简称形参),在定义函数时使用的参数叫形参,在调用函数时使用的参数叫实参。
实参可以是常量、变量或表达式,但要求它们有确定的值。
实参与形参的结合只有一种方式,即“值传递”,把实参的值赋给形参变量。
“值传递”具有单向性,只能把实参传给形参,而不能由形参回传给实参。
不同数据类型的`函数参数对主调函数中变量的作用有所不同。
函数参数可取的数据类型为基本类型、构造类型、指针类型或空类型,如图所示。
空类型表示该函数为无参函数,在此不作介绍。
其余数据类型又可分为三类:普通类型,包括基本类型、结构体类型和共用体类型;指针类型;数组类型。
函数参数为普通类型时,对函数的调用不用影响到主调函数中变量的值;函数参数为指针类型或数组类型时,对函数的调用可以修改主调函数中有关变量的值。
3普通类型变量作为函数参数普通变量作为函数参数时,对形参的修改不会影响到实参。
如下例所示,通过“值传递”,形参x保存了实参a的值,形参y保存了实参b的值,因为形参和实参是相互独立的不同变量,所以在swap函数中对形参x和y进行的交换不会反映到实参a和b中。
C语言中传值与传址
C语⾔中传值与传址⾸先介绍⼀下函数中传值与传址的概念:1. 传值:传值,实际是把实参的值赋值给⾏参,相当于copy。
那么对⾏参的修改,不会影响实参的值。
2. 传址:实际是传值的⼀种特殊⽅式,只是他传递的是地址,不是普通的赋值,那么传地址以后,实参和⾏参都指向同⼀个对象,因此对形参的修改会影响到实参。
下来⽤两个例⼦来说明:先看看这个代码#include<stdio.h>void swap(int n1,int n2){int temp;temp=n1;n1=n2;n2=temp;}int main(){int a=10;int b=20;printf("a=%d\n",a);printf("b=%d\n",b);swap(a,b);printf("a=%d\n",a);printf("b=%d\n",b);}以上代码实现的功能好像是交换两个数的数值对吧!运⾏⼀下看看结果:不对啊,和我们预想的不⼀样啊,可以看到a,b的值并没有被交换,怎么回事呢?因为a和b虽然成功把值传给了n1、n2,n1、n2也完成了它们之间数值的交换,但是也仅仅是n1、n2之间交换了,和a、b没有关系。
这是⼀次单向的传递过程,a、b能传给n1、n2,n1、n2能成功互换其数值,但n1、n2是定义在函数swap中的局部变量,当函数调⽤结束后,它俩就over了,被残忍抛弃了(⼦函数的⽣命期为⼦函数开始调⽤到结束调⽤,调⽤结束后就主动释放了),因此它们没有渠道把交换的值传回给a、b。
所以看到的是如上图的结果。
有了以上的结果,我们再来看这样⼀段代码:#include<stdio.h>void swap(int *p1,int *p2){int temp;temp=*p1;*p1=*p2;*p2=temp;}int main(){int a=10;int b=20;printf("交换前a,b的值分别为:\n");printf("a=%d\n",a);printf("b=%d\n",b);swap(&a,&b);printf("交换后a,b的值分别为:\n");printf("a=%d\n",a);printf("b=%d\n",b);} 以上代码的功能同样是实现交换两个数的数值对吧!让我们再来看看运⾏结果:很奇怪,为什么这⼉却能交换了?调试⼀下看看有什么⽞机:这是调⽤swap函数前a、b的数值与其在内存中开辟的空间的地址以及调⽤函数后时*p1、*p2的数值与其地址。
c语言函数参数传递方式三种
c语言函数参数传递方式三种
c语言函数参数传递方式有三种,它们将在下文中进行具体探讨。
首先,谈到c语言函数参数传递方式,按值传递是最常用的方式之一。
在按值传递中,函数参数实参向形参传递的内容是一个复制品,即实
参对应的副本,而形参对实参不产生任何影响。
也就是说,在按值传
递中,实参中的值并不会发生变化,而所有的改变都发生在副本上,
这就是按值传递的本质。
其次,按地址传递也是常用的一种c语言函数参数传递方式。
在按地
址传递中,函数参数实参将地址值(而不是具体的值)传递给形参,
因此,函数内部的代码可以直接读取实参的值,如果修改了实参的值,实参的值也会被修改。
最后,按引用传递是一种特殊的按地址传递,但是其使用方式却与按
地址传递不同。
在按引用传递中,实参只需要传递一个“对对象的引
用(reference)”即可,因此,函数内已经可以获取到实参的地址,
并且可以直接读取或修改实参的值,而不用把地址传递给形参。
总结以上,c语言函数参数传递方式分为三种:按值传递、按地址传递和按引用传递,这三种传递方式在某些情况下表现出不同的特点,所
以在实际开发中,根据具体需求来选择最合适的函数参数传递方式,
才能更好地完成开发任务。
C函数参数和返回值三种传递方式值传递指针传递和引用传递
C函数参数和返回值三种传递方式值传递指针传递和引用传递函数参数和返回值的传递方式可以分为三种:值传递、指针传递和引用传递。
这三种传递方式在实际应用中各有优劣,需要根据具体的情况选择合适的方式。
下面将详细介绍这三种传递方式。
值传递是最简单、最直接的参数传递方式。
它将参数的值复制给形参,在函数内部对形参的修改不会影响到实参。
值传递通常用于传递基本数据类型,例如整型、浮点型、字符型等。
在函数调用过程中,实参的值被复制到形参中,形参的修改不会对实参产生影响。
这样的传递方式可以保证函数内部的操作不会改变外部数据,使得程序更加可靠。
但是,通过值传递传递大型或复杂的数据结构时会产生较大的开销,因为需要复制整个数据结构。
此外,对于递归或大量数据的处理,使用值传递会占用较多的内存空间,影响程序的性能。
指针传递是将参数的地址传递给形参,形参通过指针访问实参的值。
使用指针传递可以在函数内部修改实参的值。
指针传递常用于需要函数内部直接修改实参值的情况,例如交换两个变量的值。
在函数调用过程中,实参变量的地址被传递给对应的指针形参,函数内部通过指针访问实参的值。
指针传递相对于值传递来说,在内存使用上更加高效,因为只需要传递地址,并不需要复制整个数据结构。
但是,指针传递需要注意指针的空指针和野指针问题,以及对指针所指向的内存进行正确的管理和释放。
引用传递是C++中特有的传递方式,它将实参的别名传递给形参,形参和实参指向同一块内存地址。
使用引用传递可以在函数内部直接修改实参的值,并且不会引入额外的内存开销。
引用传递通常用于传递复杂数据类型,例如数组和结构体等。
在函数调用过程中,实参变量的别名被传递给对应的引用形参,函数内部对引用形参的修改直接作用于实参,从而避免了复制数据结构的开销。
引用传递在使用上更加简洁,代码可读性更高。
但是,需要注意引用的生命周期和作用域,以避免引用失效或引发访问非法内存的问题。
从性能的角度来看,值传递和引用传递相对较为高效,因为不需要额外的内存开销。
c 函数传值和传址 数组
c 函数传值和传址数组
C语言中函数参数传值和传址是非常重要的概念,尤其是在处理数组时。
首先,让我们来看一下函数参数传值和传址的概念。
在C语言中,当我们调用一个函数并传递参数时,参数可以通过传值或传址的方式传递给函数。
传值意味着函数接收的是参数的拷贝,对参数的修改不会影响到原始的值;而传址意味着函数接收的是参数的地址,对参数的修改会影响到原始的值。
对于数组来说,当我们将数组作为参数传递给函数时,实际上传递的是数组的地址,因此可以说数组在函数参数传递中是以传址的方式进行的。
这意味着在函数内部对数组元素的修改会影响到原始数组。
举个例子来说明传值和传址对数组的影响。
假设有一个函数
`modifyArray`,它接收一个数组作为参数并修改数组的元素。
如果我们以传值的方式传递数组,那么在函数内部对数组元素的修改不会影响到原始数组;但如果以传址的方式传递数组,函数内部对数组元素的修改会影响到原始数组。
另外,需要注意的是,在C语言中可以通过指针来实现传址的效果。
当我们将指针作为参数传递给函数时,实际上传递的是指针的地址,这样函数就可以通过指针来修改原始值。
总的来说,对于数组来说,函数参数传递是以传址的方式进行的,因为实际上传递的是数组的地址。
这意味着在函数内部对数组元素的修改会影响到原始数组。
而如果需要以传值的方式进行数组的操作,可以考虑使用指针作为参数传递,这样就可以实现传址的效果。
希望这个回答能够帮助你理解C语言中函数参数传值和传址对数组的影响。
c语言参数表
c语言参数表(实用版)目录1.C 语言参数表概述2.参数表的组成3.参数表的传值方式4.参数表的应用示例正文一、C 语言参数表概述C 语言参数表是指在 C 语言函数定义时,位于函数名后的括号内的变量列表。
参数表主要用于在函数调用时传递数据,以便在函数内部进行相应的操作和处理。
函数参数在函数调用时按照顺序依次传递给函数,并在函数内部使用。
二、参数表的组成参数表由一系列变量组成,这些变量可以是整型、浮点型、字符型等各类数据类型。
参数表中的变量需要指定数据类型,参数表的每个元素之间用逗号分隔。
三、参数表的传值方式C 语言中参数表的传值方式分为两种:值传递和指针传递。
1.值传递:将实参的值复制一份传递给形参。
这种方式不会改变实参的值,函数内部对形参的操作不会影响到实参。
2.指针传递:将实参的地址传递给形参。
这种方式允许函数内部直接操作实参的值,对形参的操作会直接影响到实参。
四、参数表的应用示例下面是一个 C 语言参数表应用的示例,该示例展示了一个计算两个整数之和的函数:```c#include <stdio.h>int add(int a, int b) {return a + b;}int main() {int num1 = 10;int num2 = 20;int sum = add(num1, num2);printf("The sum of %d and %d is %d", num1, num2, sum);return 0;}```在这个示例中,`add`函数的参数表包含两个整数类型的变量`a`和`b`。
函数通过值传递的方式接收这两个整数,然后计算它们的和并返回。
在`main`函数中,我们调用`add`函数并将结果存储在变量`sum`中,最后输出结果。
通过以上介绍,我们可以了解到 C 语言参数表的作用和用法,以及如何根据需要编写合适的参数表。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
C 语言中参数的传值问题第1页C 语言中参数的传值一直比较含糊,今天在网上看到三个面试题的详解,感觉讲的很好,就拿来记下,方便学习和记忆。
1. 考题一:程序代码如下: void Exchg1(int x, int y) { int tmp; tmp=x; x=y; y=tmp;printf(“x=%d,y=%d/n”,x,y) }void main() {int a=4,b=6; Exchg1 (a,b) ;printf(“a=%d,b=%d/n”,a,b) }输出的结果: x=____, y=____ a=____, b=____问下划线的部分应是什么,请完成。
2. 考题二:代码如下。
Exchg2(int *px, int *py) {int tmp=*px; *px=*py; *py=tmp;print(“*px=%d,*py=%d/n”,*px,*py); } main() { int a=4; int b=6;Exchg2(&a,&b);Print(“a=%d,b=%d/n”, a, b); }输出的结果为: *px=____, *py=____ a=____, b=____问下划线的部分应是什么,请完成。
3. 考题三: Exchg2(int &x, int &y) {int tmp=x; x=y; y=tmp;print(“x=%d,y=%d/n”,x,y); } main() { int a=4; int b=6; Exchg2(a,b);Print(“a=%d,b=%d/n”, a, b); }输出的结果: x=____, y=____ a=____, b=____问下划线的部分输出的应是什么,请完成。
你不在机子上试,能作出来吗?你对你写出的答案有多大的把握? 正确的答案,想知道吗?(呵呵,让我慢慢地告诉你吧!) 好,废话少说,继续我们的探索之旅了。
我们都知道:C 语言中函数参数的传递有:值传递,地址传递,引用传递这三种形式。
题一为值传递,题二为地址传递,题三为引用传递。
不过,正是这几种参数传递的形式,曾把我给搞得晕头转向。
我相信也有很多人与我有同感吧?下面请让我逐个地谈谈这三种传递形式。
二、函数参数传递方式之一:值传递1. 一个预备的常识为了说明这个问题,我先给出一个代码: int a=4; int x; x=a; x=x+3;看好了没,现在我问你:最终a 值是多少,x 值是多少?(怎么搞的,给我这个小儿科的问题。
还不简单,不就是a==4 x==7嘛!)在这个代码中,你要明白一个东西:虽然a 值赋给了x ,但是a 变量并不是x 变量哦。
我们对x 任何的修改,都不会改变a 变量。
呵呵!虽然简单,并且一看就理所当然,不过可是一个很重要的认识喔。
2.值传递的一个错误认识先看题一中Exchg1函数的定义:void Exchg1(int x, int y) //定义中的x,y变量被称为Exchg1函数的形式参数{int tmp;tmp=x;x=y;y=tmp;printf(“x=%d,y=%d/n”,x,y)}问:你认为这个函数是在做什么呀?答:好像是对参数x,y的值对调吧?请往下看,我想利用这个函数来完成对a,b两个变量值的对调,程序如下:void main(){int a=4,b=6;Exchg1 (a,b) //a,b变量为Exchg1函数的实际参数。
/ printf(“a=%d,b=%d/n”,a,b)}我问:Exchg1 ()里头的printf(“x=%d,y=%d/n”,x,y)语句会输出什么啊?我再问:Exchg1 ()后的printf(“a=%d,b=%d/n”,a,b)语句输出的是什么?程序输出的结果是:x=6 , y=4a=4 , b=6 //为什么不是a=6,b=4呢?奇怪,明明我把a,b分别代入了x,y中,并在函数里完成了两个变量值的交换,为什么a,b变量值还是没有交换(仍然是a==4,b==6,而不是a==6,b==4)?如果你也会有这个疑问,那是因为你跟本就不知实参a,b 与形参x,y的关系了。
3.理解值传递的形式看调用Exch1函数的代码:main(){int a=4,b=6;Exchg1(a,b) //这里调用了Exchg1函数printf(“a=%d,b=%d”,a,b)}Exchg1(a,b)时所完成的操作代码如下所示。
int x=a;//←int y=b;//←注意这里,头两行是调用函数时的隐含操作int tmp;tmp=x;x=y;y=tmp;请注意在调用执行Exchg1函数的操作中我人为地加上了头两句:int x=a; int y=b;这是调用函数时的两个隐含动作。
它确实存在,现在我只不过把它显式地写了出来而已。
问题一下就清晰起来啦。
(看到这里,现在你认为函数里面交换操作的是a,b变量或者只是x,y变量呢?)原来,其实函数在调用时是隐含地把实参a,b 的值分别赋值给了x,y,之后在你写的Exchg1函数体内再也没有对a,b进行任何的操作了。
交换的只是x,y变量。
并不是a,b。
当然a,b的值没有改变啦!函数只是把a,b的值通过赋值传递给了x,y,函数里头操作的只是x,y的值并不是a,b的值。
这就是所谓的参数的值传递了。
哈哈,终于明白了,正是因为它隐含了那两个的赋值操作,才让我们产生了前述的迷惑(以为a,b已经代替了x,y,对x,y的操作就是对a,b的操作了,这是一个错误的观点啊!)。
三.函数参数传递方式之二:地址传递继续——地址传递的问题!看题二的代码:Exchg2(int *px, int *py){int tmp=*px;*px=*py;*py=tmp;print(“*px=%d,*py=%d/n”,*px,*py);}main(){int a=4;int b=6;Exchg2(&a,&b);Print(“a=%d,b=%d/n”, a, b);}它的输出结果是:*px=6,*py=4a=6,b=4看函数的接口部分:Exchg2(int *px,int *py),请注意:参数px,py都是指针。
再看调用处:Exchg2(&a, &b);它将a的地址(&a)代入到px,b的地址(&b)代入到py。
同上面的值传递一样,函数调用时作了两个隐含的操作:将&a,&b的值赋值给了px,py。
px=&a;py=&b;呵呵!我们发现,其实它与值传递并没有什么不同,只不过这里是将a,b的地址值传递给了px,py,而不是传递的a,b的内容,而(请好好地在比较比较啦)整个Exchg2函数调用是如下执行的:px=&a; //py=&b; //请注意这两行,它是调用Exchg2的隐含动作。
int tmp=*px;*px=*py;*py=tmp;print(“*px=%d,*py=%d/n”,*px,*py);这样,有了头两行的隐含赋值操作。
我们现在已经可以看出,指针px,py的值已经分别是a,b变量的地址值了。
接下来,对*px,*py的操作当然也就是对a,b变量本身的操作了。
所以函数里头的交换就是对a,b 值的交换了,这就是所谓的地址传递(传递a,b的地址给了px,py),你现在明白了吗?四.函数参数传递方式之三:引用传递看题三的代码:Exchg3(int &x, int &y) //注意定义处的形式参数的格式与值传递不同{int tmp=x;x=y;y=tmp;print(“x=%d,y=%d/n”,x,y);}main(){int a=4;int b=6;Exchg3(a,b); //注意:这里调用方式与值传递一样Print(“a=%d,b=%d/n”, a, b);}输出结果:x=6, y=4a=6, b=4 //这个输出结果与值传递不同。
看到没有,与值传递相比,代码格式上只有一处是不同的,即在定义处:Exchg3(int &x, int &y)。
但是我们发现a与b的值发生了对调。
这说明了Exchg3(a,b)里头修改的是a,b变量,而不只是修改x,y 了。
我们先看Exchg3函数的定义处Exchg3(int &x,int &y)。
参数x,y是int的变量,调用时我们可以像值传递(如:Exchg1(a,b); )一样调用函数(如:Exchg3(a,b); )。
但是x,y前都有一个取地址符号&。
有了这个,调用Exchg3时函数会将a,b 分别代替了x,y了,我们称x,y分别引用了a,b变量。
这样函数里头操作的其实就是实参a,b 本身了,也就是说函数里是可以直接修改到a,b的值了。
最后对值传递与引用传递作一个比较:1.在函数定义格式上有不同:值传递在定义处是:Exchg1(int x, int y);引用传递在这义处是:Exchg1(int &x, int &y);2.调用时有相同的格式:值传递:Exchg1(a,b);引用传递:Exchg3(a,b);3.功能上是不同的:值传递的函数里操作的不是a,b变量本身,只是将a,b值赋给了x,y函数里操作的只是x,y变量而不是a,b,显示a,b的值不会被Exchg1函数所修改。
引用传递Exchg3(a,b)函数里是用a,b分别代替了x,y。
函数里操作的是a,b。