经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » C 语言 » 查看文章
C语言的函数概念与规则你了解吗
来源:jb51  时间:2021/8/26 17:21:20  对本文有异议

一、函数概念

函数三要素
int fun(int,int,char){xxx}

函数名 (地址)输入参数输出参数

1.传入参数

实参: 调用时传入的具体值
形参: 函数内部接受的变量

2.返回值

返回函数处理的结果数据(另一种方式是函数外部使用址传递参数,来获得函数处理的数据)

二、函数参数

C语言函数传参,实际上就是copy的过程,参数类型的区别在于copy的多少的问题,当然类型不同可能存在丢失部分数据情况(copy不完整)

  1. void printAddress(int a)
  2. {
  3. //printAddress a地址:0xc
  4. printf("printAddress a地址:%p\n",a);
  5. }
  6. int main()
  7. {
  8. int a = 12;
  9. //main a地址:0xc
  10. printf("main a地址:%p\n",a);
  11. printAddress(a);
  12. return 0;
  13. }
  1. void printAddress(int a)
  2. {
  3. //printAddress a地址:0xffffff9b
  4. printf("printAddress a地址:%p\n",a);
  5. }
  6. int main()
  7. {
  8. char a = "ABCDE";
  9. //main a地址:0xffffff9b
  10. printf("main a地址:%p\n",a);
  11. printAddress(a);
  12. return 0;
  13. }
  1. void printAddress(int a)
  2. {
  3. //printAddress a地址:0xeccc1e18
  4. printf("printAddress a地址:%p\n", a);
  5. }
  6. int main()
  7. {
  8. int a = 12;
  9. int *p_a;
  10. p_a = &a;
  11. //main a地址:0x7ffeeccc1e18
  12. printf("main a地址:%p\n", p_a);
  13. printAddress(p_a);
  14. return 0;
  15. }

三、指针函数-函数名指针化

通过函数三要素可以得出,指针也可以表示函数
int (*p)(int,int,char){xxx} 与指针指向二维数组类似,指针必须要加(),来提高程序对他解读的优先级,而不是默认从右往左读

1.指针指向其他函数的函数名(标签)效果

  1. int main()
  2. {
  3. int (*printf2)(const char *,...);
  4. //HelloWOrld
  5. printf("HelloWOrld\n");
  6. printf2 = printf;
  7. //FFFF
  8. printf2("FFFF\n");
  9. return 0;
  10. }

2.指针指向其他函数的地址效果

  1. int main()
  2. {
  3. int (*printf2)(const char *, ...);
  4. //HelloWOrld 0x7fff204b50b8
  5. printf("HelloWOrld %p \n", printf);
  6. printf2 = (int (*)(const char *, ...))0x7fff204b50b8;
  7. //FFFF
  8. printf2("FFFF\n");
  9. return 0;
  10. }

3.通过二级指针,将一组函数线性化

  1. int (*p[5])(int,int);
  2. p[0]=func1;
  3. p[1]=func2;
  4. p[2]=func3;
  5. //使用效果,可以替代switch
  6. p[day](8,9);

四、函数值传递和址传递

值传递:void fun1(int a){...}传入数据a copy到函数中,函数中数据的修改不影响函数外被传入的数据
址传递:void func2(*a){...}传入数据地址&a copy到函数中,函数中数据的修改是在该地址上修改的,函数外被传入的数据也处在该内存地址上,所以会数据被修改

仅查看时用值传递
读写资源或节省资源时 使用址传递

五、函数连续空间的传递

连续空间传递,一般都会选择使用址传递,使用值传递浪费资源过多

1.结构体(变量)

值传递示例

  1. struct product_t
  2. {
  3. char name[20];
  4. int price;
  5. };
  6.  
  7. void println(struct product_t product)
  8. {
  9. strncpy(product.name, "牙刷", 20);
  10. product.price = 3;
  11. //println:牙刷
  12. printf("println:%s \n", product.name);
  13. //println:3
  14. printf("println:%d \n", product.price);
  15. }
  16. int main()
  17. {
  18. struct product_t product;
  19. strncpy(product.name, "手机", 20);
  20. product.price = 3666;
  21. println(product);
  22.  
  23. //main:手机
  24. printf("main:%s \n", product.name);
  25. //main:3666
  26. printf("main:%d \n", product.price);
  27. return 0;
  28. }

址传递示例 (通过指针)

  1. struct product_t
  2. {
  3. char name[20];
  4. int price;
  5. };
  6.  
  7. void println(struct product_t *product)
  8. {
  9. //product[0]等价于*product此处可以替换,但是需要加()让程序优先识别,即:(*product)
  10. strncpy(product[0].name, "牙刷", 20);
  11. product[0].price = 3;
  12. //println:牙刷
  13. printf("println:%s \n", product[0].name);
  14. //println:3
  15. printf("println:%d \n", product[0].price);
  16. }
  17. int main()
  18. {
  19. struct product_t product;
  20. strncpy(product.name, "手机", 20);
  21. product.price = 3666;
  22. println(&product);
  23.  
  24. //main:牙刷
  25. printf("main:%s \n", product.name);
  26. //main:3
  27. printf("main:%d \n", product.price);
  28. return 0;
  29. }

2.数组(标签)

数组int names[10];在定义时,编译器已经知道其首地址被names标签描述,因此数组作为形参时只需要传递数组的标签名和偏移量即可names[10]即可

数组址传递数据示例

  1. //C语言现在优化允许使用int p[10],便于阅读 实际上效果与int *p一致,都是址传递
  2. void println(int *p)
  3. {
  4. p[0] = 77;
  5. //println:77
  6. printf("println:%d \n", p[0]);
  7. //println:11
  8. printf("println:%d \n", p[1]);
  9. }
  10. int main()
  11. {
  12. int prices[10] = {22, 11, 55};
  13. println(prices);
  14.  
  15. //main:77
  16. printf("main:%d \n", prices[0]);
  17. //main:11
  18. printf("main:%d \n", prices[1]);
  19. return 0;
  20. }

数组址传递地址示例

  1. //C语言现在优化允许使用int p[10],便于阅读 实际上效果与int *p一致,都是址传递
  2. void println(int *p)
  3. {
  4. p[0] = 77;
  5. //println:0x7ffee8964df0
  6. printf("println:%p \n", &p[0]);
  7. //println:0x7ffee8964df4
  8. printf("println:%p \n", &p[1]);
  9. }
  10. int main()
  11. {
  12. int prices[10] = {22, 11, 55};
  13. println(prices);
  14.  
  15. //main:0x7ffee8964df0
  16. printf("main:%p \n", &prices[0]);
  17. //main:0x7ffee8964df4
  18. printf("main:%p \n", &prices[1]);
  19. return 0;
  20. }

如上两段代码,数组传递为址传递,数组标签名本身就是地址的标签,与指针非常相似

3.连续空间的只读

定义参数时使用const修饰指针所指的内存地址即可,如const char *p,这也是开发时默认的规范
读写函数形参:char *p;
只读函数形参:const char *p
如strncpy函数的源码:char *stpncpy(char *dst, const char *src, size_t n)

六、函数返回值

返回值与参数一样,也是copy的原理传递,可以copy值,也可以copy地址

  1. char func1()
  2. {
  3. char s = 'A';
  4. return s;
  5. }
  6. int main()
  7. {
  8. char s= func1();
  9. //41
  10. printf("%X",s);
  11. return 0;
  12. }

注意:指针是C语言中返回空间的唯一类型 (无法返回函数内部创建的变量地址,会被回收:异常)
int * func();

  1. char * func1()
  2. {
  3. return "HelloWorld";
  4. }
  5. int main()
  6. {
  7. char *p= func1();
  8. //HelloWorld
  9. printf("%s",p);
  10. return 0;
  11. }

工程中一般不使用上述方案(常量区存储),意义不大,通常使用静态区存储局部变量(程序结束才回收),即如下方法

  1. char * func1()
  2. {
  3. static char abc[] = "HelloWorld";
  4. return abc;
  5. }
  6. int main()
  7. {
  8. char *p= func1();
  9. //HelloWorld
  10. printf("%s",p);
  11. return 0;
  12. }

也可以使用堆区存储malloc()函数中创建的变量,注意使用完毕后一定要释放内存(free())

  1. char * func1()
  2. {
  3. char *s = (char *)malloc(50);
  4. strncpy(s,"HelloWorld",50);
  5. return s;
  6. }
  7. int main()
  8. {
  9. char *p= func1();
  10. //HelloWorld
  11. printf("%s",p);
  12. free(p);
  13. return 0;
  14. }

总结

本章主要为C语言函数概念和规则

本篇文章就到这里了,希望能给你带来帮助,也希望您能够多多关注w3xue的更多内容!

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号