C语言学习笔记(浙大翁恺版)第七周(函数部分)

7.1.1 初见函数

在第四周时候我们的作业中编写了一个计算素数和的程序

C语言学习笔记(浙大翁恺版)第七周(函数部分)_第1张图片 

高亮的部分作用是判断i是不是素数,功能单纯,占用版面大,因此我们可以将它独立出来,稍微更改一下数字。

C语言学习笔记(浙大翁恺版)第七周(函数部分)_第2张图片 

而主函数内我们也做些更改

C语言学习笔记(浙大翁恺版)第七周(函数部分)_第3张图片

 至今我们就完成了将一个全部功能都在主函数下的程序分为专用函数和主函数的转变。由此我们就可以将功能性代码和执行性代码分开,实现代码复用,精简程序。

如果同样的功能使用几乎完全一样的代码,一直复制粘贴代码,进行code duplication,这是程序质量不良的一种表现

 

7.1.2 函数的定义和调用 

函数是什么 

  • 函数是一块代码,接收零个或者多个值,完成一个功能,返回一个或零个值 

我们理解时可以与数学中的函数做类比,但是并不等同。

函数的结构

C语言学习笔记(浙大翁恺版)第七周(函数部分)_第4张图片

最外侧的大括号外的是函数头,而其内部包含的内容是函数体。这个大括号是不可以省略的

函数头中,最前面的int作为函数的返回类型,决定了函数返回值的数据类型。“isPrime”是函数名,后面的圆括号标志着isPrime是一个函数,其内部我们称之为参数表,我们用逗号分隔不同参数,参数由类型名和变量名配对组成。

调用函数

知道了函数如何定义,我们如何调用它?我们需要给出函数名+(传入给函数的参数值),确定要调用的是哪个函数,然后再依照正确的数量和顺序传递若干参数。这些值会被按顺序依次用于初始化函数中的值,当没有参数需要传入时圆括号依旧不能省略。

C语言学习笔记(浙大翁恺版)第七周(函数部分)_第5张图片

 (按顺序传递信息)

C语言学习笔记(浙大翁恺版)第七周(函数部分)_第6张图片 

 (括号不能省略)

函数返回 

当需要多次调用同一函数时,每次调用完函数后函数会回到正确的位置。接下来还会细讲

 

7.1.3 从函数中返回 

每个主函数中我们写的return 0和上面函数例子中的return ret,都是根据需要返回了一个值。有一个例子可以帮助我们认识这一点。

C语言学习笔记(浙大翁恺版)第七周(函数部分)_第7张图片 

 这是一个单一出口的程序,遇到return程序停止运行,如果后面跟了东西就会返回这个东西。可以是值,也可以是表达式。

  • 一个函数中可以有多个return语句
  • 对于void类型函数:不能使用带值的return。但是可以没有return语句。调用时不能给返回值赋值(就是说函数体内不能给返回值赋值)
  • 函数的返回值可以赋值给变量,也可以再次传递给函数,甚至可以丢弃。
  • 如果返回一个值之后没有接收这个值,这个值就会消失。

7.2.1 函数原型 

 函数先后关系

我们在之前的例子中看到,函数是写在主函数main之前的。这是因为C的编译器是从上往下顺序分析你的代码。在调用之前它需要知道函数的具体信息,同时检查你的调用是否正确。

如果想要将函数写在后面,可以在main之前写上函数头,以分号结尾。这称为函数的声明部分。也叫函数原型。

  • 声明和函数定义的函数头必须完全一致
  • 函数原型的目的是为了告诉编译器这个函数长什么样:
  • 名称、参数、返回类型
  • 函数原型里可以不写参数名只写类型,甚至可以随便写参数名。但写成一样可读性好

 

7.2.2 参数传递 

 

 调用函数 

  • 如果函数有参数,则调用函数的时候必须传递给它数量、类型正确的值
  • 可以传递给函数的值是表达式的结果,包括:
    • 字面量
    • 变量
    • 函数返回值
    • 计算结果 

C语言学习笔记(浙大翁恺版)第七周(函数部分)_第8张图片 

上图从上到下依次为: 调用字面量(常数);调用变量;变量+字面量;调用返回值+变量;计算结果+变量。

 

如果调用时给的值和定义的参数类型不匹配呢?

C编译器会悄悄帮你把类型转换好,即使和你所期望的不同,也就是说当你出错了,程序大概率会继续运行。这是C传统上最大的漏洞,C++和Java在这方面上会很严格。 

 

传递给函数的是什么?

C语言在调用函数时,永远只能将值传递给函数,也就是说,不能把变量传递给函数来改变主函数里变量的值。

举个例子,假如我们像这样写一个程序。把交换两个变量的值写成一个函数,然后在主函数里调用,这样做并不能交换两个数的值

C语言学习笔记(浙大翁恺版)第七周(函数部分)_第9张图片

 虽然swap函数里的a,b和主函数里a,b同名,但它们是分别独立的,没有关系的。也就是说,每个函数都有自己的变量空间,参数也位于这个独立的空间里,和其他函数没有关系,独立的变量不能跨界。之后我们会详细讲讲这件事。

 

形参和实参

 在过去我们把函数参数表里的参数叫做形参,把调用时候给的值叫做实参。由于容易让初学者误会实参是实际运算的参数,调用时候是把变量传递进去了,所以不建议这样称呼它们。这种称呼来自于第一种高级编程语言Fortran,因为它包含了将变量传递到函数的方式。但是C语言没有,所以我们可以认为传递的只有参数和值的区别。

因此我们可以将定义时候的参数称为参数,调用时候输入的称为值。

 

7.2.3 本地变量 

函数每次运行,都会产生一个独立的变量空间,在这个空间中的变量,是函数此次运行独有的,我们称其为本地变量(局部变量/自动变量)。 

  • 定义在函数内部的变量都叫做本地变量(我们学习至今的所有变量都是本地变量)
  • 参数表里的参数也是本地变量

生存期和作用域 

  • 生存期:变量的开始出现的时间和消失的时间
  • 作用域:在代码的什么范围内可以访问这个变量 

对于本地变量,二者的答案统一:在大括号(也可称为块)内(无论包含了多少语句)

  • 在块外定义的变量依旧可以在块内使用
  • 块内部定义的变量和外部变量重名的话,外面的变量会被覆盖(同名变量内部优先级高)
  • 本地变量不会默认初始化
  • 参数进入函数时候会初始化(使用你调用时候给的值)

7.2.4 函数庶事 (可以理解为注意事项)

无参函数(void)

  • void f(void);
  • void f();

哪个对?答案是第一个。为什么?

前面我们提到,如果你不写参数表,调用时C编译器会猜测你这里需要的类型,即使你并不想用这个类型。不写,不代表没有,只能说未知。因此调用时也许就会出错 

调用函数时的逗号到底是逗号运算符还是单纯的分隔符?

答:是单纯的标点符号,不是运算符 

函数里能不能再定义一个函数? 

答:不能,C语言规定 函数里不能嵌套定义另一个函数 。可以放声明部分或者调用别的函数。

我想声明函数的同时定义变量,可以吗?

如:int i,j,sum(int a,int b); 

答:可以,但不建议。 

返回值可以这么写吗?return(i)

答:可以,但不建议,会让人误以为return是个函数名 

那main函数也属于函数吗 ?为什么括号里不写类型?为什么要写return0?

答:是的,主函数main也是一个函数,是整个程序的入口,但不是最先执行的代码,当一些先决代码被执行后就会开始执行main函数。

对于return 0,main函数结束的时候将这个0返回给调用它的地方,让其检查程序,报告给操作系统。返回0意思是程序正确执行并结束

你可能感兴趣的:(C语言,c语言,学习)