目录
本章节我们来学习一下函数是什么,为什么要用函数,怎样取定义一个函数
相关的库函数使用可以看一下:
库函数 自定义函数
库函数是现成的函数库中可用的函数。
这些函数通常作为程序员的工具,在编程过程中被调用使用。库函数通常包含在操作系统或者编程语言的标准库中,以便程序员方便地调用这些函数来完成特定的任务,例如字符串操作、文件操作、网络操作等。库函数经过长时间的使用和测试,已经经过优化,因此程序员可以使用这些函数来提高代码的可维护性、可读性和执行效率。
字符串操作函数:如strlen()、strcpy()、strcat()、strcmp()等
动态内存分配函数:如malloc()、calloc()、realloc()、free()等。
时间函数:如time()、asctime()、mktime()等
数学函数:如sin()、cos()、tan()、log()、exp()、sqrt()等
注意:
使用库函数,必须包含 #include 对应的头文件。
如果库函数能干所有的事情,那还要程序员干什么?
所以更加重要的是自定义函数。
自定义函数和库函数一样,有函数名,返回值类型和函数参数。
但是不一样的是这些都是我们自己来设计。这给程序员一个很大的发挥空间
ret_type fun_name( para1, * )
{
statement;//语句项
}
ret_type 返回类型
fun_name 函数名
para1 函数参数
写一个函数可以找出两个整数中的最大值。
- //get_max函数的设计
- int get_max(int x, int y)
- {
- return (x > y) ? (x) : (y);
- }
- int main()
- {
- int num1 = 10;
- int num2 = 20;
- int max = get_max(num1, num2);
- printf("max = %d\n", max);
- return 0;
- }
我们来看下面的代码:
写一个函数,实现交换两个整形变量的内容。
- void Swap1(int x, int y)
- {
- int tmp = 0;
- tmp = x;
- x = y;
- y = tmp;
- }
- int main()
- {
- int num1 = 10;
- int num2 = 20;
- Swap1(num1, num2);
- printf("Swap1::num1 = %d num2 = %d\n", num1, num2);
- return 0;
- }
我们把num1和num2传参给Swap1这个函数,x 和 y 分别来接收,让其实现两个数的交换,结构如何呢?
我们发现两个值并没有实现交换,我们换一种传参方式试一下
- void Swap2(int* px, int* py)
- {
- int tmp = 0;
- tmp = *px;
- *px = *py;
- *py = tmp;
- }
- int main()
- {
- int num1 = 10;
- int num2 = 20;
- Swap2(&num1, &num2);
- printf("Swap2::num1 = %d num2 = %d\n", num1, num2);
- return 0;
- }
这次我们把num1和num2的地址传给Swap2函数,让指针变量*px和*py来接收,结果又是如何呢?
成功交换!
这就是形参和实参的区别
形式参数:
形式参数是指函数名后括号中的变量,因为形式参数只有在函数被调用的过程中才实例化(分配内存单元),所以叫形式参数。形式参数当函数调用完成之后就自动销毁了。因此形式参数只在函数中有 效。
实际参数:
真实传给函数的参数,叫实参。
实参可以是:常量、变量、表达式、函数等。
无论实参是何种类型的量,在进行函数调用时,它们都必须有确定的值,以便把这些值传送给形参。
上面 Swap1 和 Swap2 函数中的参数 &num1 , x,y,px,py都是形式参数。
在main函数中传给 Swap1 的 num1、num2 和传给Swap2函数的&num1、&num2 是实际参数。
Swap1:
我们来进入调试,查看两块代码的不同
当函数调用时,实参的值被复制到函数的形参中。
这意味着,形参在函数的局部作用域内创建,并且在函数调用结束时被销毁。
因此,在内存中,形参的值存在于函数的栈帧中,而实参的值仍然存在于调用函数的上下文中。
Swap1 函数在调用的时候,x,y拥有自己的空间,同时拥有了和实参一模一样的内容。
所以我们可以简单的认为:形参实例化之后其实相当于实参的一份临时拷贝。
Swap2:
指针变量px和py存储着num1和num2的地址,改变对px和py解引用操作后,指向的就是num1和num2这片空间的值,才能实现两者的调换
在函数调用中,参数可以通过传值调用或传址调用来传递。
传值调用是指将实参的值复制一份传递给形参的过程。
在函数内部,对形参的任何修改都不会影响到实参。
这种方式比较简单,但是如果需要传递大量的参数或者需要频繁修改参数的值,可能会比较低效
传址调用是指将实参的地址传递给形参的过程。
在函数内部,可以通过该地址直接访问实参的内容。
如果对形参进行修改,就相当于对实参进行了修改,因为它们指向同一块内存。
这种方式比较高效,但是需要注意不要意外修改实参的内容。
判断一个数是否是素数
- int isPrime(int num)
- {
- int i;
- if (num < 2)
- {
- //小于 2 的数都不是素数
- return 0; // 返回 false
- }
- for (i = 2; i * i <= num; i++)
- {
- //从 2 开始到 sqrt(num) 循环
- if (num % i == 0)
- {
- // 如果可以整除,说明不是素数
- return 0; // 返回 false
- }
- }
- return 1; // 如果上述循环完毕还没有返回 false,则说明是素数,返回 true
- }
- int main()
- {
- int num;
- printf("请输入一个整数:");
- scanf("%d", &num);
- if (isPrime(num))
- {
- printf("%d是素数\n", num);
- }
- else
- {
- printf("%d不是素数\n", num);
- }
- return 0;
- }
测试:
1 3 8 9
写一个函数,每调用一次这个函数,就会将n值增加1
- void increase(int* n)
- {
- (*n)++;
- }
- int main()
- {
- int a = 1;
- printf("a = %d\n", a);
- increase(&a);
- printf("a = %d\n", a);
- increase(&a);
- printf("a = %d\n", a);
- return 0;
- }
有关函数的内容今天就到这里,接下来还有函数的嵌套调用、声明和定义以及函数递归。
更多内容关注博主,掌握最新内容