1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > 深入理解C语言系列之函数传参的那些事儿(函数参数 指针 地址 数组)

深入理解C语言系列之函数传参的那些事儿(函数参数 指针 地址 数组)

时间:2023-12-18 02:22:43

相关推荐

深入理解C语言系列之函数传参的那些事儿(函数参数 指针 地址 数组)

文章目录

一、指针与函数之间的关系二、复制传参三、地址传参四、传一维数组(地址)五、传二维数组(地址)六、传指针数组(地址)七、指针函数和函数指针

一、指针与函数之间的关系

1、我们可以给一个函数传一个整型、字符型、浮点型的数据,也可以给函数传入一个地址。

2、函数的传参方式:复制传参(数值)、地址传参(地址值)

3、如果实参是一个普通变量,那么地址传参时,形参就需要使用一级指针;

如果实参是一个一级指针,那么地址传参时,形参就需要使用二级指针;

以此类推…

二、复制传参

#include <stdio.h>//交换数值的一个函数 void fun(int a, int b){int temp;temp= a;a= b;b= temp;printf("在函数中数值:a=%d,b=%d\n", a, b);printf("在函数中地址:a=%p,b=%p\n", &a, &b);}//测试函数 void test(){int a=30, b=100;printf("传参之前数值:a=%d,b=%d\n", a, b);printf("传参之前地址:a=%p,b=%p\n", &a, &b);fun(a, b);printf("函数结束后数值:a=%d,b=%d\n", a, b);printf("函数结束后地址:a=%p,b=%p\n", &a, &b);} int main(){test(); }

测试结果:

可以看到,形参a与实参a的地址是不同的,说明形参a与实参a就是两个独立开来的变量,因为作用域的原因,它们可以重名,但实际上是两个不同的变量。

因此,改变形参的值,并不会影响到实参的大小。

三、地址传参

1、传一维指针

#include <stdio.h>//一个交换地址的函数void fun2(int *p1, int *p2){int temp;temp= *p1;*p1= *p2;*p2= temp;printf("在函数中数值:*p1=%d,*p2=%d\n", *p1, *p2);printf("在函数中地址:p1=%p,p2=%p\n", &p1, &p2);} //测试函数 void test(){int a=30, b=100;printf("传参之前数值:a=%d,b=%d\n", a, b);printf("传参之前地址:a=%p,b=%p\n", &a, &b);fun2(&a, &b);printf("函数结束后数值:a=%d,b=%d\n", a, b);printf("函数结束后地址:a=%p,b=%p\n", &a, &b);} int main(){test();}

测试结果:

地址传参的分析方法与复制传参类似,可以看到形参的地址与实参的地址是一样的,说明实参就代表了形参,改变形参的值就是在改变实参的大小。

2、传字符串指针

#include <stdio.h>void fun(char **q){*q= "Oh my love";}int main(){char *p= "hello world";fun(&p);printf("%s", p); //输出字符串 }

这同样也是地址传参,因此会改变实参的数据值。

四、传一维数组(地址)

只要是传入一维数组的数组名,都是地址传参,会改变原来数组的数据值。

方式一:形参用一维数组,int p[]

方式二:形参用一维指针,int *p

#include <stdio.h>void fun1(int *p) //也可以用int p[] {p[2]= 520;printf("函数内:p[2]=%d\n", p[2]);printf("函数内:p[3]=%d\n", *(p+3)); //相当于p[3] }int main(){int a[10]= {10, 9, 8, 7, 6, 5, 4, 3, 2, 1};fun1(a);printf("函数结束后:a[2]=%d\n", a[2]);printf("函数结束后:a[3]=%d\n", a[3]);}

因为传递的都是数组名,也就是地址传参了,所以修改形参的值就会改变实参的大小。

五、传二维数组(地址)

传递二维数组名都是地址传参,但是只有使用p[][]数组的方式才能改变原来数组的数据值。

#include <stdio.h>void fun2(int (*p)[4]) //也可以用p[][4] {p[0][2]= 520; //这样不会改变原数组的数据*(*(p+1)+2)= 120; printf("函数内:p[0][2]=%d\n", p[0][2]);printf("函数内:p[1][2]=%d\n", *(*(p+1)+2)); //相当于p[1][2] } int main(){int a[][3]= {{10, 9, 8},{7, 6, 5}, {4, 3, 2}};fun2(a);printf("函数结束后:a[0][2]=%d\n", a[0][2]);printf("函数结束后:a[1][2]=%d\n", *(*(a+1)+2)); //相当于a[1][2]}

六、传指针数组(地址)

指针数组本质上就是一个数组,数组里面的每一个元素都是一个函数指针,返回值类型(*函数指针变量名[函数指针的个数])(形参列表);

例如:int(*p[10])(int,int);

定义了一个函数指针数组,有10个元素p[0]~p[9],每个元素都是函数指针变量,指向的函数,必须有整型的返回值,两个整型参数。

测试代码:

void fun3(int **q){int i;printf("函数内输出:\n");*(q)= "You";*(q+1)= "are";for(i=0; i<3; i++){printf("%s\n", q[i]);}} int main(){int i= 0;char *p[3]= {"I", "am", "here"};fun3(p);printf("函数结束后输出:\n");for(i=0; i<3; i++){printf("%s\n", p[i]);}}

测试结果:

七、指针函数和函数指针

指针函数:本质上就是一个函数,是一个返回指针的函数。

函数指针:本质上就是一个指针,是一个指向函数的指针。

详情请参见文章:

C语言指针深入透析(原来你一直没有搞懂C语言指针是因为没有理解其中的规律)

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。