代码编织梦想

接着上次的数组,这次我们来简单的讲讲C语言里面的函数。
函数和指针这两大块,在C语言中占据着重要的位置,是C语言中的主体和核心,所以它们的重要性也就不言而喻了。

那什么是函数呢?
1:函数是C语言的模块,一块块的,有较强的独立性,可以相互调用,也就是说,你可以在函数A中调用函数B,又可在函数B中调用函数C,不仅如此,你还可以调用函数自身(递归)。
2:函数是完成一个个特定任务的语句集合,它能完成你所想要的某种特定任务,当你要用时,只需要调用它即可,在后续的修改或是维护过程中,只需要针对这一个进行修改即可。
打个比方来理解函数:

在一个饭店里面,顾客点了一盘菜后,服务员把该菜的名字给后勤,他负责洗菜这项功能,完毕后把菜交给配菜的师傅,待菜切好后,把菜交给厨师,厨师负责炒菜,完毕后,服务员把菜端给顾客。

在上面那个比方内,有四个不同的,独立的角色:服务员,后勤,配菜师傅,厨师。
他们每一个只是负责给他们指定的任务:
服务员相当于是 main() 主函数,他是整个过程的开始,主函数也被称作 程序的接口,我们写的代码都是首先从这里执行下去的。
后勤,配菜师傅,厨师, 相当于三个不同的函数,他们执行各自的功能,互不影响,并且哪里出了问题,很快就可以确定问题的位置。

假如顾客吃到的菜有一只青虫,那我们基本可以确定出问题(bug)的是在后勤部分。

那为什么需要函数呢?

1:在我们写代码的时候,有时候会重复写一段代码,而这段代码所执行的功能,操作是一样的,只是针对的数据不一样,这个时候,将这段功能写成一个函数模块,在需要用到的时候调用即可,进而避免了写重复的代码,避免了重复性操作。
2:方便代码的维护,当我们知道哪个部分出问题后,或者需要修改某个功能,那就只需要修改那部分的代码即可。
在上面饭店的比方中,我们一下子便可知道吃到青虫时,是哪里出了问题。

这里,我将上面那个例子,写成了一个点单的小程序,将洗菜配菜做菜分别写成了三个不同的函数来演示一下:
在这里插入图片描述

在主函数体外面:
在这里插入图片描述
这三个分别是独立出来的,完成他们各自的功能。互不影响,相互独立。
若是不写成函数,那么直接在 case语句 后面分别写三条 printf ,那将会显得冗长,且如果有部分除了差错,那修改的将是三个,麻烦。


库函数和自定义函数
1: C语言为我们提供了上百个可调用的库函数,例如与字符串有关的 strlen, strcat, strlwr . 或是我们刚接触C语言时候用到的 printf, scanf, 这些都是c语言为我们提供的。在我们使用某一库函数的时候,需要在程序中嵌入(#include<>) 该函数所需要的头文件。
这也就是为啥我们在代码开头都需要写上#include <stdio.h>,因为 printf, scanf,getchar,gets,putchar()这些函数 (也称作标准I/O函数),都是在stdio头文件中。
2:自定义函数就是我们自己写的,例如我上面那个 chef(), coord()


函数的定义
这里记住一点即可:当你函数定义写在主函数之前的时候,那么就无需在主函数里面声明这个函数,只需要把函数体写在主函数前即可:
在这里插入图片描述
而若我将exp()写在下面:
在这里插入图片描述
那编译器将提示错误:
在这里插入图片描述
如果要写在主函数下面,我们则需要告诉编译器,有这个函数的存在:
在这里插入图片描述


函数按照是否有参数分为有参类型和无参类型

按照是否有返回值也分为有返回值和无返回值两种类型。

有参函数 指的是在该函数被调用的时候,主调函数通过参数向里面传递了数据。
无参函数 很好理解就是不传递数据,因为没有参数,无法获得值。
这里着重介绍下 有参函数
它的定义一般是:

函数数据类型 函数名字(参数1, 参数2, 参数3... , 参数n)
{
   语句块;
}
//函数数据类型可以是 void (空类型,不带返回值的), int, float, double, 指针类型(int *, char *s)
//参数,根据自己的需要来,你如果想传递浮点类型,那么就需要定义成浮点类型的数据类型(flaot, double)

举例:
//返回两个数字最大的一个
int max(int n1, int n2)
{
   return ((n1 > n2) ? n1 : n2);
}

//计算三个数字之和
int sum(int n1, int n2, int n3)
{
    return n1 + n2 + n3;
}

//计算字符串长度
int _strlen(char *str)
{
    int l = 0;
    while(*(str+l) != '\0' && ++l) ;
    return l;
}

在我们自定义的函数里面,括号里面的参数叫做形式参数(形参),而在主调函数里面,括号后面的参数叫做实际参数(实参),它可以是常量,变量,表达式
例如你在主调函数调用max函数的时候可以:

_max = max(12, 43);        //二者都是常量
_max = max(n1 + n2, 4 * 5);  //n1 n2为变量,进行加法操作也是一个表达式

在调用函数的时候,需要知道以下几点:
1:在调用的时候,主调函数向参数传递的是值,在调用结束后,该值不改变。
2:函数只有被调用,系统才会给它分配内存单元。
3:调用结束后,系统给他分配的内存单元立即被释放,而主调函数中的值不会改变
4:主调函数传递给被调用函数值后,被调用的函数里面可以直接用该值,但是要记住,值的数据类型要和参数的数据类型一一对应。

第一点:
函数再调用的时候,发生的是 值传递,也就是把值拷贝一份给形参,在形参里面改变其值并不影响实参的值<这里的值是单向传递的:实参 -> 形参 >:
在这里插入图片描述
在 exch() 函数中,我试图改变n的值,但是却没有改变,就是因为我仅仅只是把 n = 46 这个值给拷贝一份给了 exch() 函数,在此时的exch()函数中,它里面的n就有了 46这个值

在这里插入图片描述

对于第四点:
在数据传递的时候,若是数据类型不同,有可能会发生数据丢失等错误,例如:
在这里插入图片描述
这里的数据发生了截断。


函数的传递不仅有传值,也有传址的操作。

传值就是直接用一个变量去存储那个值
传地址就是用一个变量(指针变量)去记住那个地址

这里需要了解一个知识点:
1:数组名的值,就是一个一个指针常量。也就是第一个元素的地址,它的类型取决于数组元素的类型:如果它们是int类型,那么数组名的类型就是 “指向int的常量指针”;
为啥说是常量,因为它在定义的时候系统已经给它分配好了内存地址,也就是说,已经是无法更改了。常量是不能被更改的量。
2:如果你要在函数中,要改变主调函数中某变量的值,那么就要把地址传递给形参,
如果不需要改变,直接传递值的拷贝即可。

结合1,2两点可以理解为啥我们把数组名字作为实参传递进函数的时候可以改变原数组的值。
数组的传递的方式:

int sort(int arr[], int n);           //一维数组
sotr(arr, 10);   					    //调用

int sort(int *arr, int n);            //跟一维数组一样,指针的方式定义的
sort(arr, 10);

int sort(int arr[][4], int l, int r); //二维数组,需要告诉每个元素的数组长度
sort(arr, 4, 4);

有同学可能有疑问了,值传递和址传递有区别嘛?
其实是没的,两者可以说是一样的,因为址传递,传递的是地址,地址这个值,由形参里面的指针变量存放着。

看下面一个易错的例子:

void swap(int a, int b)
{
	int t;
	t = a;
	a = b;
	b = t;
}

我若调用

swap(a, b);  //a = 2, b = 3;

在主函数中,调用swap函数后,输出的结果是啥?
答案依然是2,3
为啥呢?
因为我仅仅只是把 a = 2, b = 3 这个值给拷贝进了swap的形参中去,不影响主调函数中的变量的值。
根据要注意的点中,第二个要点,我想在被动用的函数中就改变主调函数中参数的值,那么我就需要把地址传递进去,也就是进行址传递,那么我函数的定义就需要借助指针:
在这里插入图片描述

为什么会如此呢?
因为我把变量的地址给传递进去了后,形参中的指针变量对地址进行的操作,就会影响该内存空间的值,进而反映到主调函数中去,也就是发生了改变。

本次涉及到了指针的知识,指针又是一个比较难理解的地方,要理解指针,就需要的内存地址有一个深刻的理解,在学习指针的时候,可以用纸和笔在纸上勾画下 数据方框和地址方框,用箭头来表示指针指向地址方框来理解指针。
函数后面还有更加复杂的递归函数,一句话来概括递归就是:递归是函数调用自身的过程。
这里就不多做解释,因为我也并不是对递归有一个深刻的理解,所以也无法讲清楚来。

<如有错误请指出>
Gakki

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_43342294/article/details/84724383

c语言函数操作大全----(超详细)-爱代码爱编程

fopen(打开文件) 相关函数 open,fclose 表头文件 #include<stdio.h> 定义函数 FILE * fopen(const char * path,const char * mode); 函数说明 参数path字符串包含欲打开的文件路径及文件名,参数mode字符串则代表着流形态。 mode有下列几种形态字符

c语言函数及其调用_hello.world!的博客-爱代码爱编程_c语言引用函数

一、C语言函数 1.概念:函数是一组一起执行一个任务的语句,每个c程序都必须有一个main函数,程序员可以把代码划分到不同的函数当中去,在逻辑上,划分通常是根据每个函数执行一个特定的任务来进行的。c标准库提供了可以大量调用的库函数,比如,printf,strcmp等。 2.函数的定义 c语言中函数的一般定义如下: return_type Funct

c语言函数-爱代码爱编程

  函数的概念        每个C程序都至少有一个函数,即主函数 main() ,如果程序的任务比较简单,全部的代码都写在main()函数中,但是,在实际开发中,程序的任务往往比较复杂,如果全部的代码都写在main()函数中,main()函数将非常庞大臃肿,结构复杂,代码重复。        我们可以根据程序的逻辑和任务的分工把代码划分到不同的自定

C/C++编程笔记:指针篇!从内存理解指针,让你完全搞懂指针-爱代码爱编程

C语言最核心的知识就是指针,所以,这一篇的文章主题是「指针与内存模型」!说到指针,就不可能脱离开内存,学会指针的人分为两种,一种是不了解内存模型,另外一种则是了解。 不了解的对指针的理解就停留在“指针就是变量的地址”这句话,会比较害怕使用指针,特别是各种高级操作。而了解内存模型的则可以把指针用得炉火纯青,各种 byte 随意操作,让人直呼 666。

史上最全C语言函数详解笔记-爱代码爱编程

函数 目录 函数是什么库函数自定义函数函数参数函数调用函数的嵌套调用和链式访问函数的声明和定义函数递归1.函数是什么 数学里的函数f(x)=2*x+1 但是C语言中的函数是什么样的呢?在维基百科中的定义为子程序。 在计算机科学中,子程序,是一个大型程序中的某部分代码, 由一个或多个语句块组 成。它负责完成某项特定任务,而且相较于其他代 码,具备相

c语言函数定义的语法格式,C语言函数 -C语言函数定义的语法格式-爱代码爱编程

C语言程序是由多个零件组合而成的,而函数就是最主要的组合零件。C语言程序的主体部分就是一个 main( ) 函数,它在 C语言程序中是必不可少的,每一个 C 程序都首先从 main( ) 函数开始执行。 C语言函数是什么 在前面的学习中,我们知道在 main( ) 函数中可以通过 printf( ) 函数实现屏幕输出显示的功能,通过 scanf(

【C语言】函数基础知识点总结-爱代码爱编程

目录 1.函数定义 2.函数类型 2.1自定义函数 2.2库函数 3.实参与形参 4.函数的调用 5.函数的声明 6.函数的嵌套调用和链式访问 6.1嵌套调用 6.2链式访问 7.函数递归 博主水平有限,文章中若有错误,望读者们斧正。 1.函数定义 维基百科中,函数的定义是 “在计算机科学中,子程序(英语:Subrouti

C语言函数详解-爱代码爱编程

目录 一、函数的定义与分类 1.定义 2.分类 二、库函数 1.库函数存在的意义 2.库函数的学习和使用 三、自定义函数 1.自定义函数的组成 2.示例 (1)写一个函数找出两个整数的最大值 (2)写一个函数交换两个整型变量的内容 四、函数的参数 1. 实际参数(实参) 2.形式参数(形参) 五、函数的调用 1.传值调用

c语言中的常用函数_叶子落落落落落了的博客-爱代码爱编程

1.数学函数 头文件 #include <math.h> 幂函数: pow 对数函数:log/log10 log()函数在数学中的原型是以e为底的对数函数ln(x)。 log10()函数在数学中的原型是以10为底的对数函数log10(x)。 取整函数:round/floor/ceil 四舍五入函数:round()函数 向下取整函数

函数重载和extern“c“_我不是二时四k的博客-爱代码爱编程

C++基础 1、进程空间内存分布及编译过程 2、内联函数 2、函数重载和extern"C" 文章目录 C++基础前言一、函数重载是什么?二、为什么C语言不能进行函数重载,C++可以进行函数重载?1.函数符号2

c语言常用函数集锦_c语言 考试常用需要自己写的函数-爱代码爱编程

n以内的素数 int count = 0; int a[1000]; int i, j, n; a[0] = 0; a[1] = 0; scanf("input n = %d", &n); for (i = 2;

c语言中常用的函数_c语言常用函数_爱睡觉的小馨的博客-爱代码爱编程

C语言中常用的函数 1、putchar()函数2、getchar()函数3、pow( a , b )函数4、sqrt( a )函数5、fabs(a)函数6、puts(字符数组)函数——输出字符串的函数7、get

c语言中的函数(详解)_c语言函数大全及详解-爱代码爱编程

目录 1.函数是什么 2.c语言中函数的分类: 2.1. 库函数 2. 自定义函数 3. 函数的参数 3.1 实际参数(实参) 3.2 形式参数(形参) 4. 函数的调用: 4.1 传值调用 4.2 传址调用 5. 函数的嵌套调用和链式访问  5.1 嵌套调用  5.2 链式访问 6.函数的声明和定义 6.1 函数声明: 6