目录
-
C语言中函数的概念
定义:在计算机科学中,子程序(英语:Subroutine, procedure, function, routine, method, subprogram, callable unit),是一个大型程序中的某部分代码,由一个或多个语句块组 成。它负责完成某项特定任务,而且相较于其他代码,具备相对的独立性。
一般会有输入参数并有返回值,提供对过程的封装和细节的隐藏。这些代码通常被集成为软件库。
-
库函数
我们在开发的过程中每个程序员都可能用的到, 为了支持可移植性和提高程序的效率,所以C语言的基础库中提供了一系列类似的库函数,方便程序员进行软件开发。
- 库函数是C语言标准中约定好,由编译器的厂商提供实现。
下面拿strlen( )函数举例:
C语言标准规定:
- 函数的功能——求字符串的长度
- 函数名——strlen
- 参数 ——const char* str
- 返回类型——size_t
int strlen(const char* str);
{
}//函数内部由各厂商提供实现
总结:
C语言中常见的库函数有: IO函数 字符串操作函数 字符操作函数 内存操作函数 时间/日期函数 数学函数 其他库函数
-
函数使用示例
1.pow函数 (求一个数(base)的多少次方(exponent))
所需头文件
- 强转后
- 强转前
2. strcpy函数(将source指向的字符串,拷贝到destination所指向的数组空间里面去,且包含结束的字符(\0))
所需头文件
- 执行
3.memset函数(将ptr所指向的那块空间的前num个字节的内容设置成value值)
所需头文件
- 执行
下面分享给大家一个有关库函数的链接:http://www.cplusplus.com/reference/
总结:学会阅读文档,可以帮我们快速上手一些库函数 ;而想要读懂文档,英语的学习是至关重要的。
-
自定义函数
自定义函数和库函数一样,有函数名,返回值类型和函数参数。但是不一样的是这些都是我们自己来设计。这给程序员一个很大的发挥空间。
-
函数的基本组成(函数名,参数,返回类型,函数体)
ret_type fun_name(para1, * )
{
statement;//语句项
}
ret_type 返回类型
fun_name 函数名
para1 函数参数
- 示例
写一个函数,可以找出两个整数中的最大值
#include <stdio.h>
int get_max(int x, int y)
{
if (x > y)
return x;
else
return y;
}
int main()
{
int a = 0, b = 0;
scanf("%d %d", &a, &b);
int m = get_max(a, b);
printf("%d\n", m);
//也可以写成 printf("%d\n",get_max(a,b));
//直接打印函数的返回值
}
运行结果:
-
传值调用和传址调用
1. 如何交换两个数
想要交换两个数,需要设置一个中间变量,代码如下
int tmp = 0;
tmp = num1;
num1 = num2;
num2 = tmp;
解释:
2.传值调用
void Swap(int x, int y)
{
int tmp = 0;
tmp = x;
x = y;
y = tmp;
}
int main()
{
int num1 = 0;
int num2 = 0;
scanf("%d %d", &num1, &num2);
printf("交换前:num1=%d num2=%d\n", num1, num2);
Swap(num1, num2);
printf("交换后:num1=%d num2=%d", num1, num2);
return 0;
}
这里我们运行一下:
为什么这里num1和num2的值并没有发生交换呢?下面引入形参和实参的概念帮助大家进一步理解。
-
形参和实参
形参 :
形式参数是指函数名后括号中的变量,因为形式参数只有在函数被调用的过程中才实例化(分配内 存单 元),所以叫形式参数。
形式参数当函数调用完成之后就自动销毁了。因此形式参数只在函数中有效。
实参:
真实传给函数的参数,叫实参。
实参可以是:常量、变量、表达式、函数等。
无论实参是何种类型的量,在进行函数调用时,它们都必须有确定的值,以便把这些值传送给形 参。
通过调试我们在了解一下上面的代码为什么没有将交换后的值输出出来。
通过观察x和y的地址、内容,以及num和num2的地址、内容,我们可以看到实际上在函数内部x和y的值是发生了交换的,但由于x、y和num1、num2是完全独立的空间(可以看到它们的地址不同),函数的内部并没有和外部的变量产生联系。
可以概述为:函数调用的时候,将实参传递给形参;形参其实是实参的一份临时拷贝;对形参的修改,不会改变形参
那么如何让函数的内部来操纵外部的变量呢?这里就用到我们的传址调用了
3.传址调用
void Swap(int* p1, int* p2)
{
int tmp = 0;
tmp = *p1;
*p1 = *p2;
*p2 = tmp;
}
int main()
{
int num1 = 0;
int num2 = 0;
scanf("%d %d", &num1, &num2);
printf("交换前:num1=%d num2=%d\n", num1, num2);
Swap(&num1,&num2);
printf("交换后:num1=%d num2=%d", num1, num2);
return 0;
return 0;
}
运行结果:
解释:
这里我们以指针的形式,我们传参的时候相当于把num1和num2的地址直接传了过去,这样通过p1和p2便可以找到num1和num2的地址,在通过解引用操作便可以直接找到num1和num2啦。
-
应用场景
传值调用:函数的形参和实参分别占有不同内存块,对形参的修改不会影响实参
传址调用:传址调用是把函数外部创建变量的内存地址传递给函数参数的一种调用函数的方式。 这种传参方式可以让函数和函数外边的变量建立起真正的联系,也就是函数内部可以直接操作函数外部的变量。
-
函数的嵌套调用和链式访问
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;
}
注意:函数可以嵌套调用,但是不能嵌套定义。
如:
void test()
{
int Add(int x, int y)
{
return x + y;
}
}
//错误
2.链式访问
把一个函数的返回值作为另外一个函数的参数。
int main()
{
printf("%d\n", strlen("abc"));//链式访问
//将strlen函数的返回值当做了printf函数的参数
return 0;
}
int main()
{
char arr1[20] = { 0 };
char arr2[ ] = "abc";
printf("%d\n", strlen(strcpy(arr1,arr2)));
return 0;
}
执行结果: