函数——“C”

简介: 函数——“C”

各位CSDN的uu们新年快乐呀,祝大家越来越开心,越来越优秀。那行,让我们进入今天的正题,来了解了解函数,函数是什么,C语言中函数是如何分类的,函数参数,函数调用等一系列小知识点,就让我们一起进入函数的世界吧


为什么要使用函数


 函数是什么


C语言是模块化程序设计语言。一个C程序可由一个主函数和若干个其他函数构成。一个较大的程序可分为若干个程序模块,每一个模块用来实现一个特定的功能。在高级语言中用子程序实现模块的功能。子程序由函数来完成。


在计算机科学中,子程序(英语:Subroutine, procedure, function, routine, method, subprogram, callable unit),是一个大型程序中的某部分代码, 由一个或多个语句块组成。它负责完成某项特定任务,而且相较于其他代码,具备相对的独立性。


函数间的调用关系:由主函数调用其他函数,其他函数也可以互相调用。同一个函数可以被一个或多个函数调用任意多次。


C语言中函数的分类:


   1.库函数


   2.自定义函数


库函数


为什么会有库函数?


1. 我们知道在我们学习C语言编程的时候,总是在一个代码编写完成之后迫不及待的想知道结果,想 把这个结果打印到我们的屏幕上看看。这个时候我们会频繁的使用一个功能:将信息按照一定的格 式打印到屏幕上(printf)。


2. 在编程的过程中我们会频繁的做一些字符串的拷贝工作(strcpy)。


3. 在编程是我们也计算,总是会计算n的k次方这样的运算(pow)。


像上面我们描述的基础功能,它们不是业务性的代码。我们在开发的过程中每个程序员都可能用的到, 为了支持可移植性和提高程序的效率,所以C语言的基础库中提供了一系列类似的库函数,方便程序员进行软件开发。 那怎么学习库函数呢?


  我们可以用到MSDN,这是一个专门查询库函数的软件

image.png

我们还可以用到cplusplus,也是可以查询库函数的使用功能以及函数的实现

image.png

image.png

image.png

这些工具可以让我们更加方便地了解库函数,但是,有一个问题,就是这些网站一般都是全英文,那么我们还是要把英语学好的,把英语学好尤为重要,小雅兰的目标就是赶紧把英语四六级证书拿到手啦,其余的也不敢奢求,哈哈哈,收!


自定义函数


怎样定义函数


为什么要定义函数


      函数必须“先定义,后使用”。


      定义函数包括以下几个内容:


           (1)指定函数的名字


           (2)指定函数的类型


           (3)指定函数的参数名字和类型


           (4)指定函数应当执行什么操作


怎样定义无参函数


 定义无参函数的一般形式为:


      类型名 函数名()


     {


          声明部分


          语句部分


     }


怎样定义有参函数


 定义有参函数的一般形式为:


      类型名 函数名(形式参数表列)


      {


            声明部分


            语句部分


      }


 下面,我来给大家举个例子看一下,以便我们更好地理解如何定义有参函数

int max(int x,int y)
{
  int z;//函数体中的声明部分
  z=x>y?x:y;
  return z;
}

定义空函数


 定义空函数的一般形式为:


     类型名 函数名()


     {}


 我还是来给大家举个例子看一下


  dummy()


  { }


主调函数调用空函数时,只表明这里要调用一个函数,但函数本身什么工作也不做,等以后扩充函数功能时补充上。


我们来举个例子,写一个函数来交换两个整型变量的内容


我们首先肯定会这样想

#include<stdio.h>
void swap(int x,int y)//形式参数
{
   int tmp=x;
   x=y;
   y=tmp;
}
int main()
{
   int a=0;
   int b=0;
   scanf("%d %d",&a,&b);
   printf("交换前:a=%d b=%d\n",a,b);
   swap(a,b);//实际参数
   printf("交换后:a=%d b=%d\n",a,b);
   return 0;
}

我们来运行一下我们刚刚写的代码,发现,结果怎么和我们预想的不一样呢?

image.png

我们仔细来想想,a和b是有自己的空间的,x和y也是有自己的空间的,x和y的的确确交换了,但是,实参传递给形参的时候,形参是实参的一份临时拷贝,对实参的修改是不会影响实参的。 所以,a和b不会交换。


事实证明,我们这样的做法肯定是不行,那我们不用这个传值调用的方法,又该怎么做呢?不如,我们传它的地址试试吧

#include<stdio.h>
void swap(int* pa,int* pb)
{
   int tmp=*pa;//tmp=a
   *pa=*pb;//a=b
   *pb=tmp;//b=tmp
}
int main()
{
   int a=0;
   int b=0;
   scanf("%d %d",&a,&b);
   printf("交换前:a=%d b=%d\n",a,b);
   swap(&a,&b);
   printf("交换后:a=%d b=%d\n",a,b);
   return 0;
}

来,我们一起来运行一下此代码

image.png

哦豁,结果发现,传地址的方法果然可以,a和b的果真交换了,此方法称为传址调用


函数的参数


实际参数(实参):


真实传给函数的参数,叫实参。


实参可以是:常量、变量、表达式、函数等。


无论实参是何种类型的量,在进行函数调用时,它们都必须有确定的值,以便把这些值传送给形 参。


形式参数(形参):


形式参数是指函数名后括号中的变量,因为形式参数只有在函数被调用的过程中才实例化(分配内 存单元),所以叫形式参数。


形式参数当函数调用完成之后就自动销毁了。因此形式参数只在函数中有效。


上面的*pa,*pb就是形式参数,a,b就是实际参数


函数的调用


函数调用的一般形式


函数调用的一般形式为:


    函数名 (实参表列)


说明:


  (1)如果是调用无参函数,则“实参表列”可以没有,但括弧不能省略


  (2)如果实参表列包含多个实参,则各参数间用逗号隔开。实参与形参的个数应相等,类型应匹配。实参与形参按顺序对应,一一传递数据。


调用函数的方式


按函数在程序中出现的位置来分,可以有以下三种函数调用方式:


 (1)作为一个函数语句


   把函数调用作为一个语句,这时不要求函数带回值,只要求函数完成一定的操作。如,print_star().


 (2)作为函数表达式的一部分


  函数出现在一个表达式中,这种表达式称为函数表达式。这时要求函数带回一个确定的值以参加表达式的运算。如,c=2*max(a,b);


 (3)作为函数的实参


 将函数调用作为一个函数的实参。


 例如:m=max(a,max(b,c));


  其中max(b,c)是一次函数调用,它的值作为max另一次调用的实参。m的值是a、b、c三者中的最大值。


对被调用函数的声明和函数原型


1.首先被调用的函数必须是已经存在的函数(是库函数或用户自己定义的函数)。但光有这一条件还不够。


2.如果使用库函数,还应该在本文件开头用#include命令将调用有关库函数时所需用到的信息“包含”到本文件夹中来。


3.如果使用用户自己定义的函数,而该函数的位置在调用它的函数(即主调函数)的后面,应该在主调函数中对被调用的函数作声明。


函数原型的一般形式为:


   1.函数类型 函数名(参数类型1,参数类型2......)


   2.函数类型 函数名(参数类型1,参数名1,参数类型2,参数名2......)


       声明的作用是把函数名、函数参数的个数和参数类型等信息通知编译系统,以便在遇到函数调用时,编译系统能正确识别函数并检查调用是否合法。


注意:


    函数的“定义”和“声明”的区别:


     函数的定义是指对函数功能的确立,包括指定函数名、函数值类型、形参及其类型、函数体等,它是一个完整的、独立的函数单位。


     函数的声明的作用则是把函数的名字、函数类型以及形参的类型、个数和顺序通知编译系统,以便在调用该函数时系统按此进行对照检查。


下面,我来给大家举一个例子说明一下


 例:输入两个实数a和b,用一个函数求出a^2+b^2.

#include<stdio.h>
double sum(double x,double y)//定义sum函数
{
   double z=0.0;
   z=x*x+y*y;
   return z;//把变量z的值作为函数值返回
}
int main()
{
   double a=0.0;
   double b=0.0;
   printf("please enter a and b:\n");
   scanf("%lf %lf",&a,&b);
   double c;
   c=sum(a,b);
   printf("sum is %lf\n",c);
   return 0;
}

我们来运行一下结果

image.png

我还想给大家拓展一个知识点


 传值调用:函数的形参和实参分别占有不同内存块,对形参的修改不会影响实参。


 传址调用:传址调用是把函数外部创建变量的内存地址传递给函数参数的一种调用函数的方式。


                   这种传参方式可以让函数和函数外边的变量建立起真正的联系,也就是函数内部可以                      直接操作函数外部的变量。


函数的嵌套调用和链式访问


  嵌套调用就是在调用一个函数的过程中,又调用另一个函数


   例:输入4个整数,找出其中最大的数。用函数的嵌套调用来处理。

#include<stdio.h>
int max2(int a,int b)
{
   if(a>b)
    return a;
   else 
    return b;
}
int max4(int a,int b,int c,int d)
{
  int m=0;
  m=max2(a,b);
  m=max2(m,c);
  m=max2(m,d);
  return m;
}
int main()
{
   int a=0;
   int b=0;
   int c=0;
   int d=0;
   int max=0;
   printf("please enter 4 interfer numbers:\n");
   scanf("%d %d %d %d",&a,&b,&c,&d);
   max=max4(a,b,c,d);
   printf("max=%d\n",max);
   return 0;
}

诶嘿,运行一波走起

image.png

函数可以嵌套调用,但是不能嵌套定义。


链式访问:把一个函数的返回值作为另外一个函数的参数。  

#include<stdio.h>
int main()
{
   //注:printf函数的返回值是打印在屏幕上字符的个数
   printf("%d", printf("%d", printf("%d", 43)));
   return 0;
}

此程序的结果应是4321.

首先,打印43,这毋庸置疑,43是两个字符,所以返回2,2是一个字符,然后又返回1.

image.png

好啦,小雅兰今天的内容就到这里了,函数在C语言中真的是很重要的存在,我们要认真学,学会使用上面介绍的那些工具,多刷一点和函数有关的习题,这样才能保证学得更好。


另外,函数中十分重要的内容——递归。我们留到下一篇文章中再去详细讲,我自认为,递归是一个很难的东西,确实挺耗费时间,可只要弄明白了这个问题,以后多数题目都可以利用递归来解,几行代码就可以解决非常复杂的问题。下一篇文章,我们会讲解函数递归和著名的青蛙跳台阶,敬请uu们期待!!!


最后,我还是要说,新年快乐,冲冲冲!


相关文章
|
3月前
函数(二)
函数(二)
13 0
|
4月前
|
开发工具 Windows
GetMessage()函数使用时的注意
GetMessage()函数使用时的注意
28 0
|
4月前
|
存储 程序员 C语言
函数(1)
函数(1)
53 0
|
4月前
|
人工智能
函数练习
用菜单的形式分别选择百钱买百鸡,九九表,水仙花数。
21 0
|
8月前
|
算法 程序员 编译器
最简单的函数,看看就会了
最简单的函数,看看就会了
|
11月前
|
算法 编译器 API
8.函数
8.函数
54 0
|
12月前
函数加强
在我们日常开发中,如果要遍历一个文件夹下的所有文件,通常使用递归来实现;
|
Java vr&ar
函数那些题 — P1
函数那些题 — P1
函数那些题 — P1