函数的参数
实际参数(实参):
真实传给函数的参数,叫实参。
实参可以是:常量、变量、表达式、函数等。
无论实参是何种类型的量,在进行函数调用时,它们都必须有确定的值,以便把这些值传送给形参。
形式参数(形参):
形式参数是指函数名后括号中的变量,因为形式参数只有在函数被调用的过程中才实例化(分配内存单元),所以叫形式参数。形式参数当函数调用完成之后就自动销毁了。因此形式参数只在函数中有效。
对比下这段代码与上面实现交换两个整型变量函数swap2
//实现成函数,但是不能完成任务 void Swap1(int x, int y) { int tmp = 0; tmp = x; x = y; y = tmp; } int main() { int num1 = 1; int num2 = 2; Swap1(num1, num2); printf("Swap1::num1 = %d num2 = %d\n", num1, num2); return 0; }
运行结果:
上面 Swap1 和 Swap2 函数中的参数 x,y,px,py 都是形式参数。
在main函数中传给 Swap1 的 num1 , num2 和传给 Swap2 函数的 &num1 ,&num2 是实际参数。
由于形式参数在函数中使用完后直接就被销毁了,所以根本传不会我们的主函数里打印,因此才导致未实现num1与num2的交换。
注意
Swap1 函数在调用的时候, x , y会拥有自己的空间,同时拥有和实参一模一样的内容。
所以我们可以简单的认为:形参实例化之后其实相当于实参的一份临时拷贝。
三.函数的调用
1.传值调用
函数的形参和实参分别占有不同内存块,对形参的修改不会影响实参
2.传址调用
传址调用是把函数外部创建变量的内存地址传递给函数参数的一种调用函数的方式。
这种传参方式可以让函数和函数外边的变量建立起真正的联系,也就是函数内部可以直接操作函数外部的变量。
有关传值调用与传址调用相关的小练习:
打印素数的函数
//写一个函数判断是不是素数 //并把1-200之间的结果打印出来 #include<math.h> int is_prime(int i) { int j = 0; for (j = 2; j <=sqrt(i); j++)//sqrt为平方根 { if (i % j == 0) { return 0; } } return 1; } int main() { int i = 0; int count = 0; for (i = 101; i < 201; i += 2) { int ret = is_prime(i); if(ret == 1) { printf("%d ", i); count++; } } printf("\n 一共%d个素数", count); }
二分法查找函数
用函数的形式实现二分法查找 int Find(int arr[], int k, int sz) { int left = 0; int right = sz - 1; while (left <= right) { //int mid = (left + right) / 2; int mid=left+(right-left)/2;//防止栈溢出 if (arr[mid] == k) { return mid; break; } else if(arr[mid]<k) { left = mid + 1; } else { right = mid - 1; } } return 1; } int main() { int arr[10] = { 1,2,3,4,5,6,7,8,9,10 }; int k = 7; int sz = sizeof(arr) / sizeof(arr[0]); int ret=Find(arr, k, sz); if (ret == 1) { printf("找不到\n"); } else printf("找到了,下标是%d", ret); return 0; }
上面代码就不多解释了,之前都写过博客解释,链接如下:
在C语言中如何打印某个范围中满足某些条件的数(素数,闰年,水仙花数等)
【C语言】带你玩转经典算法用二分法在一个有序数组中查找某个数
四.函数的嵌套调用和链式访问
函数和函数之间可以根据实际的需求进行组合的,也就是互相调用的。
1. 嵌套调用
函数可以嵌套调用,但是不能嵌套定义。
示例代码如下:
#include<stdio.h> void new_line() { printf("hehe\n"); } void three_line() { int i = 0; for(i=0; i<3; i++) { new_line(); } } int main() { three_line(); return 0; }
嵌套定义。以下代码连编译都过不去。
#include<stdio.h> void new_line() { printf("hehe\n"); void three_line() { int i = 0; for (i = 0; i < 3; i++) { printf("%d ", i); } } } int main() { three_line(); return 0; }
2.链式访问
把一个函数的返回值作为另外一个函数的参数。
举例说明:
#include <stdio.h> int main() { printf("%d", printf("%d", printf("%d", 43))); //结果是啥? //注:printf函数的返回值是打印在屏幕上字符的个数 return 0; }
printf函数的返回值是打印在屏幕上字符的个数
第一个printf打印“43”
- 第二个printf打印此时在屏幕上的字符个数,也就是“2”
第三个printf同理打印字符个数“1”
这就是上面这个代码结果出现的原因
六.函数的声明和定义
1.函数声明:
1). 告诉编译器有一个函数叫什么,参数是什么,返回类型是什么。但是具体是不是存在,函数声明决定不了。
2). 函数的声明一般出现在函数的使用之前。要满足先声明后使用。
3). 函数的声明一般要放在头文件中的。
2.函数定义:
函数的定义是指函数的具体实现,交待函数的功能实现。
test.h的内容
放置函数的声明
//函数的声明 int Add(int x, int y);
test.c的内容
放置函数的实现
#include "test.h" //函数Add的实现 int Add(int x, int y) { return x+y; }
这种分模块的写法曾在我们之前的五子棋以及扫雷游戏程序中多次出现,以下是博客链接,感兴趣可以去看看
【C语言】项目实战——快速0基础上手五子棋游戏(内附源码)
【C语言】万字教学,带你分步实现扫雷游戏(内含递归函数解析),剑指扫雷,一篇足矣
总结
以上就是今天的所有内容了,函数的基本使用方法以及调用该涉及到的应该都涉及到了。
如果你有任何疑问欢迎在评论区指出或者私信我,我看到后会第一时间回复的哦!
新人博主创作不易,如果感觉文章内容对你有所帮助的话不妨三连一下这个新人博主再走呗。你们的支持就是我更新的动力!!!
(可莉请求你们三连支持一下博主!!!点击下方评论点赞收藏帮帮可莉吧)