目录
cplusplus.com - The C++ Resources Network
6.3 写一个函数,每调用一次这个函数,就会将num的值增加1。
因为最近确实很忙,很多事堆到一起,所以东西出的频率会降低一些(可怜)。那我们直接进入正题吧。
1.函数是什么?
函数的本质是子程序,子程序就是一个大型程序中的部分代码,实现一个个功能,用来完成某项特定的任务,具有高内聚低耦合的性质(即独立性强,只完成自己的某项任务,不与外界过多联系)。
1.1库函数
所谓库函数,实际上就是一堆函数的仓库,每个函数的功能由代码实现,而里面的函数代码就是大牛们自己编写的,他们将一些我们经常要使用的函数进行功能封装,写到一个个函数中,如打印函数、字符串的拷贝函数、平方函数、多次方运算函数等,这些常用函数按照类别被放在一个个函数库中,方便人们直接调用,目的是为了减少人们的使用成本,极大地增加了便利性。
那么到底都有些什么库函数呢?可在该网站中进行查看 :
cplusplus.com - The C++ Resources Network
该网站可当作函数库使用,用于查询各种库函数,十分方便(如果对英语有抵触的人也可以用谷歌翻译或者浏览器页面翻译,但还是建议掌握基本的计算机英语,对前沿技术的学习十分有帮助)
1.2自定义函数
库函数里面可以调用我们经常用到的函数,实现基本功能,是面向所有人的,但仍有许多功能需要程序员自己来编写以便于实现自己想要的功能,自定义函数给了程序员很大的发挥空间,你想要的所有功能都可以由自己编写和设计。
如一个简单地小函数,求两个整数的最大值
#pragma warning(disable:4996)
#include <stdio.h>
//get_max函数的设计
int MyMax(int x, int y)
{
return (x > y) ? (x) : (y);
}
int main()
{
int num1, num2;
scanf("%d %d", &num1, &num2);
int max = MyMax(num1, num2);
printf("max = %d\n", max);
return 0;
}
2.函数的参数
2.1实参:
可以是常量、变量表达式、函数、指针等,实参有着确定的值,是在函数调用时真实传递给函数的参数。
2.2形参:
用来接收传递给函数的实参,在调用函数时发生形参实例化,进行对实参的临时拷贝,开辟内存,只有此时形参才具有实际意义,一旦函数结束,形参就会被销毁,内存又被释放掉
如上面求两个数较大值得函数MyMax中,num1,num 2 是传递给函数的实参,x,y是形参,在函数调用时,发生临时拷贝,为x y开辟内存,发生形参实例化,执行完MyMax后,x y被销毁,内存释放。
注意:
在发生形参实例化的时候,形参拷贝实参时其形参本身也要开辟空间,因此形参和实参虽然值相等,但存储地址是不同的,因此在改变形参时,实参并不会随之改变,就如同两个一样的房子,烧了甲房子,乙房子依然在且完好。
3.函数的调用
3.1传值调用:
形参和实参实际占有不同的内存块,形参不影响实参
可以发现在上图中,swap交换函数明明没有错误,为什么调用前后x,y值依然相等呢?实际上,Swap函数确实把x,y的值进行了交换,只不过交换的x,y是另外地址中存储的x,y(形参x,y拷贝实参x,y开辟新的地址),而原地址的x,y值并未发生交换。这叫做传值调用。
3.2传址调用:
将实参的地址传递给形参存储,形参根据该地址可以修改实参的值,但要注意的是,形参本身依然开辟了一个新的空间,这个空间用来存储实参的地址,此时形参和实参可以建立起真正的联系
我们来对上面的交换函数进行修改
//交换两个整型变量
#pragma warning(disable:4996)
#include<stdio.h>
void Swap(int* x, int* y)
{
int tmp = *x;
*x = *y;
*y = tmp;
return;
}
int main()
{
int x, y;
scanf("%d %d",&x,&y);
printf("交换之前——x=%d,y=%d\n", x, y);
Swap(&x,&y);
printf("交换之后——x=%d,y=%d\n", x, y);
return 0;
}
上面程序中:函数的实参是x的地址和y的地址,而用来接收这两个地址的形参是指针变量(用指针变量接收地址,该指针变量指向指针所指向的目标),即*x就是x,*y就是y,由于直接更改原地址中的值,所以实参会进行变量的交换
4.函数的嵌套和链式访问
先补充一下printf的返回值:
printf函数在显示中打印了多少个字符就返回多少,如printf(“54”)的返回值就是2,因为5和4 是两个字符
4.1嵌套调用:
通过函数来调用另一个函数,实现函数嵌套
4.2链式访问:
将一个函数的返回值作为另一个函数的参数
5.函数的声明和定义
函数的声明和定义我们在前面已经进行了一定的区分,相信大家都有了一定的了解,在此处不在进行赘述,只进行一定的小复习记忆。
- 函数定义只能定义一次,而函数声明可以进行多次声明。
- 函数声明相对于函数定义的区别是函数声明并没有函数体。
- 函数声明实际上就是告诉编译器有一个函数叫什么,参数是什么,返回类型是什么。但是具体是不是存在,函数声明决定不了,函数定义来决定一个函数是否存在.
- 函数的定义是指函数的具体实现,用来交代函数的具体 功能实现。
- 函数的声明一般出现在函数的使用之前。要满足先声明后使用。
- 函数的声明一般要放在头文件中的(头文件中不进行定义)。
6.小练习
6.1写一个函数可以判断一个数是不是素数。
#include<stdio.h>
#include<math.h>
int main()
{
int count = 0;
for (int n = 1; n < 150; n+=2)
{
int j;
for (j = 2; j <=sqrt(n); j++)
{
if (n % j == 0)
{
break;
}
}
if (j > sqrt(n))
{
printf("%d ", n);
count++;
}
}
printf("\n%d", count);
return 0;
}
6.2写一个函数判断一年是不是闰年。
//判断1000~2000之间的闰年
#pragma warning(disable:4996)
#include<stdio.h>
int main()
{
for (int i = 1000; i <= 2000; i++)
{
if(((0==i%4)&&(0!=i%100))||(0==i%400))
{
printf("%d ",i);
}
}
return 0;
}
6.3 写一个函数,每调用一次这个函数,就会将num的值增加1。
#pragma warning(disable:4996)
#include<stdio.h>
int Add(void)
{
static int num = 1;
return ++num;
}
int main()
{
int x = 10;
while (x)
{
printf("%d ", Add());
x--;
}
//调用函数,使得num每次增加1
return 0;
}
本篇把函数的概念大致讲清,但特意漏过了函数的递归,我将把函数的递归作为单独的一章,进行第一次对递归的浅析。大家晚安(留个赞吧——)