当前位置: 首页 > news >正文

大神之路-起始篇 | 第9章.计算机科学导论之【程序设计语言】学习笔记

欢迎关注「WeiyiGeek」公众号

点击 👇 下方卡片 即可关注我哟!

设为星标⭐每天带你 基础入门 到 进阶实践 再到 放弃学习

涉及 网络安全运维、应用开发、物联网IOT、学习路径 、个人感悟 等知识

  花开堪折直须折,莫待无花空折枝 


作者主页:[ https://www.weiyigeek.top ]

作者博客:[ https://blog.weiyigeek.top ]

作者答疑学习交流群:请关注公众号后回复【学习交流群


文章目录:

第 4 部分 计算机软件与算法

第 9 章 程序设计语言

  • 9.1 语言演化

  • 9.2 语言翻译

    • (1) 编译

    • (2) 解释

    • (3) 翻译

  • 9.3 编程模式

    • (1) 过程式模式

    • (2) 面向对象模式

    • (3) 函数式模式

    • (4) 声明式模式

  • 9.4 共同概念

    • (1) 标识符

    • (2) 数据类型

    • (3) 语句

    • (4) 子程序


计算机科学导论学习笔记

前言:当前作为一名IT互联网从业者,计算机技术日新月异,每天都有新概念、新技术的出现,而像我这样的万金油来说,越学到后面就越吃力,遇到瓶颈问题也随之增多,因为本身非科班出身,加之半路出家,针对于计算机基础知识掌握不牢或者说是不完整,所以我痛定思痛,下定决心重新学习计算机相关基础知识,从计算机科学导论,到计算机组成原理,到计算机网络、到操作系统,到数据结构,到程序算法、到应用开发、到安全运维开发。

今天 (2022年9月1日) 便从大神之路-起始篇,我们要站在巨人们的肩膀上,进行计算机科学导论的 学习,我将总结学习成果笔记,帮助后续入门学习的朋友。

随着现代计算机的发明,带来了新的学科,即计算机科学(简称计科)一词上一个非常广泛的概念,在此处我没将其定义为计算机相关的问题,现在计算机科学被划分成几个领域,总结归纳为两大类系统领域应用领域.

  • 系统领域:涵盖那些与硬件和软件构成直接有关的领域,例如计算机体系结构、计算机网络、安全问题、操作系统、算法、程序设计语言以及软件工程。

  • 应用领域:涵盖了与计算机使用有关的领域,例如数据库、云物联和人工智能。

参考书籍:【计算机科学导论-第三版 (Foundations Of Computer Science - Third Edition) 】作者:[美] 贝赫鲁兹.佛罗赞 (Behrouz Forouzan)

PS: 当下已经出第四版了(推荐)


第 9 章 程序设计语言

9.1 语言演化

计算机语言是指编写程序时,根据事先定义的规则(语法)而写出的预订语句集合。

计算机语言已经度过了从机器语言,到汇编语言,到高级语言的演化。

1) 机器语言

早期,计算机唯一的程序设计语言就是机器语言,每台计算机都有其自己的机器语言,它由01二进制数组成,在电气元件中分别表示关和开电路。

缺点:

  • 严重依赖计算机,不同计算机机器不能执行已编写运行的机器语言。

  • 使用机器语言编写程序单调、乏味,还易错。

370ae0d7be4f9f7c4906a06a353c1415.png

2) 汇编语言

汇编语言是由带符号或助记符(符号语言)的指令和地址组成,目的是为了替代机器语言。

汇编语言代码通过汇编程序将其翻译成为机器语言,其缺点是仍然需要程序员在硬件上花费大部分精力,并且由于每条机器指令都必须单独编码,则效率比较低下。

常用助记符:

LOAD  : 读取寄存器中数据。
STORE : 将数据存储到寄存器中。
ADDI  : 将两个寄存器数据相加。
HALT : 停止运行。

cffd680d242debbd60a375e49edc9f3a.png

3) 高级语言

高级语言的发展是为了解决(摆脱)汇编语言开发的低效、繁琐的细节,让程序员可以从关注计算机转到关注要解决的问题,即将精力集中在应用程序上,而不是计算机结构的复杂性上。

高级语言可以将编写代码程序移植到不同计算机操作系统中执行,同样它也需要经过解释或者编译流程将其转为机器语言,所以在高级语言又分解释型高级语言编译型高级语言

  • 编译型高级语言: 将源代码编译成机器码(机器语言),再由计算机运行机器码(二进制程序),只需编译一次,运行速度快,执行效率高,但依赖编译器,跨平台性差些。

    COBOL、Pascal、Ada、C、C++、Java以及现在很火的Go语言。

  • 解释型高级语言:程序不需要编译,但需要翻译成中间代码、解释器对中间代码进行解释运行,所以程序在运行时才翻译成机器语言,但每执行一次都要翻译一次,因此效率比较低、依赖解释器,跨平台性好。

    BASIC、Bat 批处理、Shell 脚本、Perl 、PHP、Python、Javascript

    例如,使用Go语言演示两个数相加。

package main
import "fmt"
func main() {
  // 定义
  var a int
  var b int
  var result int
  // 赋值
    a = 127
    b = 128
  // 计算
  result = a + b
  // 结果
  fmt.Println(result)
}

输出结果:255


9.2 语言翻译

前面提到,为了在计算机上运行程序,程序需要被翻译成它要运行在其他的计算机的机器语言。

高级语言程序 :被称为源程序

目标程序:被翻译成的机器语言程序

(1) 编译

编译程序通常把整个源程序翻译成目标程序。

(2) 解释

解释器会把源程序翻译成目标程序,而解释是指把源程序中的每一行翻译成目标程序中相应的行,并执行它的过程。

在解释中的两种趋势:

  • 解释的第一种方法

    在Java语言之前的有些解释式语言(如BASIC和APL)使用一种称为解释的第一种方法的解释过程,因为缺少其他任何的名字,所以称为解释的第一种方法。在这种解释中,源程序的每一行被翻译成被其使用的计算机上的机器语言,该行机器语言被立即执行。如果在翻译和执行中有任何错误,过程就显示消息,其余的过程就被中止。程序需要被改正,再次从头解释和执行。第一种方法被看成是一种慢的过程,这就是大多数语言使用编译而不是解释的原因。

  • 解释程序的第二种方法

    随着Java的到来,一种新的解释过程就被引入了,Java语言能向任何计算机移植,其为了取得可移植性,源程序到目标程序的翻译分成两步进行编译解释

    Java源程序首先被Java编译器编译,创建Java的字节代码,字节代码看起来像机器语言中的代码,但不是任何特定计算机的目标代码,它是一种虚拟机的目标代码,该虚拟机称为Java虚拟机或JVM,字节代码然后能被任何运行JVM模拟器的计算机编译或解释,也就是运行字节代码的计算机只需要JVM模拟器,而不是Java编译器。

(3) 翻译

编译和解释的不同在于,编译在执行前翻译整个源代码,而解释一次只翻译和执行源代码中的一行(因此效率低下)。

但是两种方法都遵循图中显示的相同的翻译过程:

53516d449542bff3d0228e48c12b3029.png

  1. 词法分析器: 一个符号接一个符号地读源代码,创建源语言中的助记符表。

    例如,5个符号w、h、i、1、e被读入,组合起来就形成了C、C++或Java语言中的助记符while.

  2. 语法分析器: 一组助记符,找出指令。

    例如,语法分析器使用助记符“X”、"=”、“0” 创建C语言中的赋值语句“x=0”

  3. 语义分析器: 检查语法分析器创建的句子,确保它们不含有二义性,而计算机语义通常情况下是无二义性的,意味着这一步骤或者是在翻译器中被省略。

  4. 代码生成器: 将每条指令将转化为一组程序将要在其上运行的计算机的机器语言。


9.3 编程模式

当下,计算机语言按照它们使用的解决问题的方法来分类,因此模式是计算机语言看待要解决问题的一种方式。

计算机语言可分为四种模式:过程性、面向对象、函数式和声明式

  • 面向过程:FORTRAN、COBL、BASIC、C 语言、Pascal、Ada

  • 面向对象:Smalltalk、C++、Visual、Basic、C#、Java、Python

  • 函数式:LISP、Scheme

  • 声明式:Prolog

(1) 过程式模式

在该模式中,我们把程序看成是操纵被动对象的主动主体。例如,我们在日常生活中遇到许多被动对象石头、书、灯等, 一个被动对象本身不能发出一个动作,但它能从主动主体接收动作。

在该模式下的程序就是主动主体,该主体使用称为数据或数据项的被动对象, 作为被动对象的数据项存储在计算机的内存中,程序操纵它们, 为了操纵数据主动主体(程序)发出动作,称之为过程。例如,考虑一个打印文件内容的程序,为了能被打印,文件需要存储在内存中(或一些像内存一样的寄存器中)。

文件是一个被动对象或一个被动对象集合, 对象(文件)是一个能接收print动作或其他一些动作(如删除、复制等)的独立实体。打印(print)过程通常包括了需要告诉计算机如何打印文件中每一个字符的所有动作,它是是编写的一个独立实体,程序只是触发它。即为了避免每次需要打印文件时都编写一个新过程,我们可编写一个能打印任何文件的通用过程,当过程被调用触发时,我们可以传递实际要打印的文件名给过程,这样便使得一个过程调用两次,分别打印不同的文件。

如果我们考虑过程和被作用于的对象,那么过程式模式的概念就变得更为简单,且容易理解。这种模式的程序由三部分构成:对象创建部分、一组过程调用和每个过程的一组代码。有些过程在语言本身中已经被定义, 我们可通过组合代码来建立新的过程。

例如,下图中显示了程序如何能调用不同的预定义过程,打印或删除不同的目标文件,以及过程式程序的三个组成部分。

f0d9706c25570c2d1870f0d598ec50a4.png

常见的过程式语言

  1. FORTRAN ( FORmula TRANsIation) :它是第一代高级语言,由Jack Backus 领导下的一批IBM工程师所设计,于1957年变成商用的,在50年后的今天它仍然是科学或工程应用中的理想语言。

    语言版本:FORTRAN. FORTRAN U、FORTRAN IV, FORTRAN 77、FORTRAN 99 和HPF(高性能FORTRAN),以及最新版本(HPF) 用于高速多处理器计算机系统。

    语言特点:

  • 高精度算法。

  • 处理复杂数据的能力。

  • 指数运算(a^b)

  1. COBOL (COmmon Business-Oriented Language): 由一批计算机专家在美国海军的Grace Hopper指导下设计出来,作为商业编程语言使用。

    语言特点:

  • 快速访问文件和数据库。

  • 快速更新文件和数据库。

  • 生成大量的报表。

  • 界面友好的格式化的输出。

  1. Pascal :由Niklaus Wirth于1971年在瑞士的苏黎世发明,根据17世纪发明Pascaline计算器的法国数学家、哲学家Blaise Pascal来命名,尽管Pascal成为学术中最流行的语言,但它从未在工业中达到同等流行的程度,现在的过程化语言归功于该语言(发展)。

    设计目标:通过强调结构化编程方法来教初学者编程。

  1. C 语言:由贝尔实验室的Dennis Ritchie在20世纪70年代初期发明的,最初用于编写操作系统和系统软件(UNIX操作系统的大部分是用C编写),当前 C 语言仍然是效率最高的语言,针对操作系统、以及嵌入式开发必学。

    语言特点:

  • 有一个结构化的高级编程语言应有的所有高级指令,使程序员无需知道硬件细节。

  • 具有一些低级指令,使得程序员能够直接、快速地访问硬件。相对于其他高级语言,C更接近于汇编语言,这使得它对系统程序设计员来说是一种好语言。

  • 是非常有效的语言,指令短。这种简洁吸引了想编写短程序的程序员。

  1. Ada :其命名是为了纪念世界上第一位程序员[阿达·洛芙莱斯](Ada Lovelace),旨在整合美军事系统中运行着上百种不同的程序设计语言。

    语言特点:

  • Ada有其他过程式语言那样的高级指令。

  • Ada有允许实时处理的指令,从而便于过程控制。

  • Ada具有并行处理能力,可以在具有多处理器的主机上运行。

(2) 面向对象模式

该模式处理活动对象,而不是被动对象,通常此类对象只需要接收合适的外部刺激来执行其中的一个动作。例如,我们生活中遇到的许多活动对象汽车、自动门、洗盘机等。

在面向对象模式中的文件能把所有的被文件执行的过程(在面向对象模式中称为方法)打包在一起,这些过程有打印、复制、删除等,仅仅向对象发送相应请求(打印、复制、删除等),文件就会进行相应操作。

此处比较过程式模式和面向对象模式,可以看出过程式模式中的过程是独立的实体, 但面向对象模式中的方法是属于对象领地的

c5afa679f66267be9ce08fe81e5f6454.png

类 (Class)

说到面向对象就不得不提到类(Class), 通常相同类型的对象(如文件)需要一组方法,方法显示了这类对象可操作的描述(属性)或者动作(方法),例如 C++、Java和C# (读作"C sharp”)等面向对象语言使用称为类的单元

面向对象语言特点:

  • 属性与方法:在该类语言中,通常我们会在类中定义对象的属性和方法,例如 动物(Animal)类包括 的名称、外观、颜色属性,以及动物吃食物的方法。

  • 继承性:即一个对象能从另一个对象继承,便于为已存在类的添加一些新的特性。例如,Cat 动物猫,继承 Animal 类,则可以继续添加喜欢的食物属性,以及猫吃🐠的方法。

  • 多态性:指我们可以定义一些具有相同名字的操作,而这些操作在相关类中做不同的事情,例如,我们定义了两个类:矩形(rectangle)和 圆(circular),都是从几何形状类继承下来的,我们定义名字都为area的两个操作,一个在矩形类中;一个在圆类中,它们分别计算矩形或圆的面积。

例如,此处以Go语言为例演示面向对象语言类的使用。

package main
import "fmt"
// 父类
type Animal struct{ name string } // 属性
func (a *Animal) voice(v string) { // 方法
  fmt.Printf("我是动物,我叫 %v, 我会叫 %s,", a.name, v)
}


// 子类 - 狗
type Dog struct {
 eat string  // 属性
 *Animal     // 继承父类
}
func (d *Dog) love() { // 方法
  fmt.Printf("狗狗喜欢吃的食物是 %v.\n", d.eat)
}


// 子类 - 狗
type Cat struct {
  eat string // 属性
  *Animal   // 继承父类
}
func (c *Cat) love() { // 方法
  fmt.Printf("猫猫喜欢吃的食物是 %v.\n", c.eat)


}


func main() {
    // 实例化对象
  d1 := &Dog{
    //注意嵌套的是结构体指针
    Animal: &Animal{
      name: "小黄",
    },
    eat: "bone",
  }
  d1.voice("汪汪.汪汪.")
  d1.love()


  c1 := &Cat{
    //注意嵌套的是结构体指针
    Animal: &Animal{
      name: "小白",
    },
    eat: "fish",
  }
  c1.voice("喵喵.喵喵.")
  c1.love()
}

执行结果:

我是动物,我叫 小黄, 我会叫 汪汪.汪汪.,狗狗喜欢吃的食物是 bone.
我是动物,我叫 小白, 我会叫 喵喵.喵喵.,猫猫喜欢吃的食物是 fish.

常见的过程式语言

  1. C++ : 是由贝尔实验室Bjame Stroustrup等人开发出来的,是比C语言更高级的一种计算机编程语言,它使用类来定义相似对象的通用属性以及可以应用于它们本身的各种操作。

    语言特点:C++语言的设计遵循三条基本原则特性封装、继承和多态

  2. Java:当前后端开发占有率最高的语言之一,由Sun Microsystems公司开发的,它在C和C++的基础上发展而来,但是C++ 的一些特性(如多重继承等)从语言中被移除,从而使Java更健壮。在Java中的程序可以是一个应用程序也可以是一个小程序,应用程序是指一个可以完全独立运行的程序,小程序则是嵌入在超文本标记语言

    语言特点:

  • 程序的执行时,将构建一个类并把它传给编译器,由编译器来调用类的方法。

  • 许多线程执行(几行代码同时执行),线程是指按顺序执行的动作序列。

(3) 函数式模式

该模式下程序被看成是一个数学函数,函数是把一组输入映射到一组输出的黑盒子。例如,求和可以被认为是具有n个输入和1个输出的函数,该函数实现n输入值相加得到总和并最终输出求和结果。

函数式语言主要实现下面的功能:

  • 1.函数式语言预定义一系列可供任何程序员调用的原始(原子)函数。

  • 2.函数式语言允许程序员通过若干原始函数的组合创建新的函数。

例如,定义一个称为first的原始函数,由它来完成从一个数据列表中抽取第一个元素的功能。再定义另一个函数rest,由它完成从一个数据列表中抽取出除第一个元素以外的所有元素,通过两个函数的组合使用,可以在一个程序中定义一个函数来完成对第三个元素的抽取。

3c1cbfba3d97c772dca6ec3522f42171.png

常见的函数是语言:

  1. LISP(LISt Programming):表处理解释语言是20世纪60年代早期由麻省理工学院科研小组设计开发的,它是一种把表作为处理对象的语言。

  2. Scheme:由麻省理工学院在20世纪70年代早期开发的,此时表处理解释语言没有统一标准化,不久之后就有许多不同的版本流传于世,该语言定义了一系列原始函数来解决问题,函数名和函数的输入列表写在括号内,结果是一个可用于其他函数输入的列表。

    例如,有一个函数car,用来从列表中取出第一个元素,第二个函数cdr用来从列表中取出除第一个元素以外的所有元素。

    两个函数如下:

    car 2 3 5 7 9  => 2

    cdr 2 3 5 7 9 => 3 5 7 9

    现在可通过该组合来完成从列表中取出第三个元素的函数。

    (car (cdr (cdr 2 3 5 7 9 ) ) ) => 取 5

(4) 声明式模式

也称为说明式,该模式依据逻辑推理的原则响应查询,它是在由希腊数学家定义的规范的逻辑基础上发展而来的,并且后来发展成为一阶谓词演算(first-order predicate calculus)。逻辑推理以推导为基础,逻辑学家根据已知正确的一些论断(事实),运用逻辑推理的 可靠的准则推导出新的论断(事实)。

例如,逻辑学中著名的推导原则如下:

8fc1c4547c172d1ef148af1cd265c367.png

说明式语言

  1. Prolog (PROgramming in LOGic):它是最著名的说明性语言,它是由法国人A.Colmerauer 于1972年设计开发的,Prolog中的程序全部由事实和规则组成。


9.4 共同概念

此节中,通过对一些过程式语言的快速浏览,发现其共同概念,并且其中某些概念对大多数面向对象语言也适用,因为创建方法时面向对象模式使用过程式模式。

(1) 标识符

所有计算机语言的共同特点之一就是都具有标识符,标识符允许给程序中对象命名,即对象的名称.

例如,计算机中每一个数据都存储在一个唯一的地址中,我们可以数据对象命名,然后给出数据的名字就可以让编译器去跟踪数据实际存放的物理地址。

(2) 数据类型

其定义了一系列值及应用于这些值的一系列操作,每种数据类型值的集合称为数据类型的域,而大多数语言都定义了两类数据类型,即简单数据类型复合数据类型

1) 简单数据类型

该类型有时又称为原子类型、基本类型、标量类型或内建类型,是不能分解成更小数据类型的数据类型,强制性语言已经定义一些简单数据类型:

    • 整数类型(int):是不包括小数部分的完整的数。整数的取值范围依赖于语言。有些语言支持多种整数大小。

    • 实数类型(float):是带小数部分的数字。

    • 字符类型(char):是被语言使用的潜在字符集中的符号,例如,ASCII或Unicode,占 1 B空间大小。

    • 布尔类型(boolean):是只取两个值(真或假)的数据类型。

2) 复合数据类型

该类型是一组元素,其中每个元素都是简单数据类型或复合数据类型(这是递归定义),大多数语言定义了如下的复合数据类型:

  • 数组(array)是一组元素,其中每个元素具有相同类型,例如 C 语言的数据类型。

  • 记录(list)是一组元素,其中的元素可以具有不同的类型,例如 Python 语言的列表类型。

# C
int array[10] = {1,2,3,4,5,6,7,8,9,10};


# Python
list1 = ['唯一极客', 2, 'weiyigeek', [1, 3, 4]]

3) 变量声明与初始化

变量是存储单元的名字,数据项在内存中可能占据多个地址,名字(作为地址的替代)使程序员从地址中解放出来,只需在程序如何执行的层次上考虑。

  • 变量声明:大多数过程式语言和面向对象语言要求变量在使用前被声明,声明警告计算机被赋予名字和类型的变量将在程序中使用,要求计算机预留出相应的存储区域。

  • 变量初始化:虽然存储在变量中的数据值在程序执行过程中可能改变,但大多数过程式语言允许变量在它声明时进行初始化,初始化就是在变量中存储一个值(实际上是存储在寄存器中)。

# 例如,在C、C++和Java中,我们可以定义三种变量数据类型 字符、整数和实数,并赋值
# 变量声明
char c;
int number;
double result;


# 声明时进行初始化
char c='a';
int number=1024;
double result=256.128;

4) 字面值

字面值是程序中使用的预定义的值,在大多数程序设计语言中,可以有整数、实数、字符和布尔字面值,还可以有字符串字面值,为了把字符和字符串字面值从变量名和其他对象中区分开,大多数语言要求字符字面值被括在单引号中,如'A',而字符串字面值被括中双引号中,如"Anne"。

例如,当半径存储在变量r中,需要计算圆的面积时,可以使用表达式π x r2其中π(pi)的近似值就是被用作字面值,此处以Go语言为例。

// Go
package main
import (
  "fmt"
  "math"
)
func main() {
  fmt.Printf("%f\n", math.Pi)   //直接输出pi的值
  fmt.Printf("%.2f\n", math.Pi) //保留两位小数
  fmt.Printf("%f\n", math.Pi*math.Pow(4, 2)) // 当半径为 4 时 πr^2 计算其圆的面积
}

执行结果为:

3.141593
3.14
50.265482

5) 常量

在程序中出了字面值以外不能在运行时被改变的量,称其为常量。

大多数编程语言定义常量(类似于变量)是一个可以存储值的名字的位置,但不同与变量的是其在声明初始化(需指明类型)后其值便不能够被改变。

// c or c++
const float flagNum = 10.24

6) 输入输出

几乎所有的程序都需要输入和(或)输出数据,大多数程序设计语言使用一些预先定义好的函数完成输入和输出。

  • 输入:数据或者通过语句或者通过预先定义的函数来完成输入。

  • 输出:数据或者通过语句或者通过预先定义的函数来完成输出。

// c
#include <stdio.h>
void main()
{
  int a,b,c;
  printf("input a,b,c\n"); // 输出
  scanf("%d%d%d",&a,&b,&c); // 输入 三个 整数
  printf("a=%d,b=%d,c=%d",a,b,c); // 输出
}

C 语言格式字符说明:

%a,%A 读入一个浮点值(仅C99有效) 
  %c 读入一个字符
  %d 读入十进制整数
  %i 读入十进制,八进制,十六进制整数
  %o 读入八进制整数
  %x,%X 读入十六进制整数
  %c 读入一个字符
  %s 读入一个字符串,遇空格、制表符或换行符结束。
  %f,%F,%e,%E,%g,%G 用来输入实数,可以用小数形式或指数形式输入。
  %p 读入一个指针
  %u 读入一个无符号十进制整数
  %n 至此已读入值的等价字符数
  %[] 扫描字符集合
  %% 读%符号

7) 表达式

表达式是由一系列操作数运算符简化后的一个单一数值,例如 3 + 2 - 5 = 0

  1. 操作数:用于接收一个运算符的动作,对于任何一个运算符可能有1、2或更多个操作数。

  2. 运算符:是用来完成一个动作的特定语言的语法记号。

算数运算符:即常见的加、减、乘、除等符号。

关系运算符:即用于比较两个数的大小关系。

逻辑运算符:即判断逻辑值(True、False)组合后的新值。

6bb0f5e086614e8fac720ad9c0c02fcf.png

(3) 语句

每条语句都使程序执行一个相应的动作,它被直接翻译成一条或多条计算机可执行的指令。

1.赋值语句:即给变量赋值,例如 C、C++和Java使用 "=" 赋值,其他语言 Go 、Ada、Pascal 则使用 := 来赋值。

2.复合语句:即包含零个或多个语句的代码单元,其被称为块,例如,Javascript 中的代码块。

{
  x = 1;
  y = 20;
}

3.控制语句:即我们在数据算法中提到的三种结构顺序、选择、循环

// 选择
if (条件) ... else ...
switch (条件) ... case ...

// 循环
while(条件) ...
for(int i = 0; i < 0; i++) {}
do .... while(条件)

d153a146a0541c34f565aa22a01c52b4.png

(4) 子程序

子程序(称为函数更贴切)的概念在过程式语言中极其重要,在面向对象语言中的作用要少些。

子程序(即理解为函数)使程序变得更结构化,更便于协同开发,帮助检査错误,完成特定任务的子程序能一次编写多次调用,就像在编程语言中的预定义过程一样。

  • 局部变量:即变量的作用域,在子程序内部定义的变量,其声明周期随着函数调用而产生,结束而销毁。

  • 参数:通常我们需要给子程序传递参数,在主程序中称为实际参数,在子程序中称为形式参数,所以在参数传递时分为传之传引用两种方式

    传值参数:主程序和子程序创建两个不同的对象(变量),在程序中创建的对象属程序,在子程序中创建的对象属于子程序,即传入到子程序中实际参数是独立的,在子程序内部处理加工的后的参数不会影响改变传入的变量值。

    传引用参数:传引用被设计来允许子程序改变主程序中变量的值,在程序向子程序传递参数变量(实际上它是内存的地址)被主程序和子程序共享,即在子程序内部处理加工的后的参数会影响改变传入的变量值。

  • 返回值:子程序(函数)通常是返回一个或者多个值。

  • 实现:子程序概念在不同的语言中被不同地实现,在C和C++中子程序被实现为函数

此处,以C语言为例:

#include <stdlib.h>


 // 传递参数(形式参数)
int value_swap(int a, int b) {
    int tmp = 0;
    if (a > b) {
       tmp = a;
       a = b;
       b = tmp;
    } 
    printf("子程序(函数内部)a = %d , b = %d \n",a , b); // 不会更改成子程序外部的变量a,b值
    return tmp;
} 


// 引用参数(形式参数)
void reference_swap(int *a, int *b) {
    int tmp = 0;
    if (a > b) {
       tmp = *a;
       *a = *b;
       *b = tmp;
    } 
    printf("子程序(函数内部)a = %d , b = %d\n",*a , *b); // 会更改成子程序外部的变量a,b值
    printf("a 变量地址 %p , b 变量地址 %p\n", a , b);
}


int main()
{
    int a = 8;
    int b = 2;
    printf("主程序 a = %d , b = %d \n",a , b);
    value_swap(a, b); // (实际参数)
    printf("经过值传递 value_swap 子程序(函数)后,主程序 a = %d , b = %d \n\n",a , b);
    
    printf("主程序 中 a 变量地址 %p , b 变量地址 %p\n", &a , &b);  // 变量地址 与 子函数内部变量地址一致
    reference_swap(&a,&b); // (实际参数)
    printf("经过值引用 reference_swap 子程序(函数)后,主程序 a = %d , b = %d \n",a , b);
}

执行结果:

主程序 a = 8 , b = 2 
子程序(函数内部)a = 2 , b = 8 
经过值传递 value_swap 子程序(函数)后,主程序 a = 8 , b = 2 

主程序 中 a 变量地址 0x7ffd748ca05c , b 变量地址 0x7ffd748ca058
子程序(函数内部)a = 2 , b = 8
a 变量地址 0x7ffd748ca05c , b 变量地址 0x7ffd748ca058
经过值引用 reference_swap 子程序(函数)后,主程序 a = 2 , b = 8

本文至此完毕,尽情期待下一章节,更多技术文章请关注公众号或访问作者技术站点!

原文地址: https://blog.weiyigeek.top/2018/1-1-1.html


亲,文章都看完了,不关注一下吗?扫描点击卡片即可关注我哟!

1eeaf2b42cb1eef0d62ebe986d445ad5.jpeg

偷偷的告诉你哟?极客全栈修炼】微信小程序已经上线了,

你可以直接在微信里面直接浏览博主博客了哟,后续将上线更多有趣的功能。

点击 👇 下方卡片,即可进入【极客全栈修炼】微信小程序!


fda51d2865843c2cd6c86588901dfaa4.png 学习书籍推荐260d0f88cab6b44d27744dd3448ab3b7.png


079914a7d159225b701178340fdf4495.png 往期发布文章72ff45739db5996e4b61c415e2c9f12c.png

大神之路-起始篇 | 第1章.计算机科学导论之【基础绪论】学习笔记

大神之路-起始篇 | 第2章.计算机科学导论之【数字系统】学习笔记

大神之路-起始篇 | 第3章.计算机科学导论之【数据存储】学习笔记

大神之路-起始篇 | 第4章.计算机科学导论之【数据运算】学习笔记

大神之路-起始篇 | 第5章.计算机科学导论之【计算机组成】学习笔记

大神之路-起始篇 | 第6章.计算机科学导论之【计算机网络】学习笔记

欢迎各位志同道合的朋友一起学习交流,更多网络安全、系统运维、应用开发、物联网实战、全栈文章,尽在

【作者 WeiyiGeek 博客 - https://blog.weiyigeek.top 】站点!

温馨提示: 由于作者水平有限,本章错漏缺点在所难免,希望读者批评指正,并请在文章末尾留下您宝贵的经验知识,联系邮箱地址 master@weiyigeek.top 或者关注公众号 WeiyiGeek 联系我。

文章书写不易,如果您觉得此篇文章还不错的朋友,请给这篇专栏 【点个赞、投个币、收个藏、关个注转个发留个言、赞个助】,这将对我的肯定,我将持续发布更多优质文章,谢谢!

b72542c24ff3ed3dc230060a4d82264f.gif

👇👇👇 点击下方【"阅读原文"】,即可获取更多有趣的知识!

相关文章:

  • Python 的Tkinter包系列之四:对话框
  • 大神之路-起始篇 | 第8章.计算机科学导论之【数据算法】学习笔记
  • IDET变化检测模型
  • javascript基本语法(持续补充)
  • Spring Boot开发之Mybatis
  • 卷王杯 easy unserialize
  • 常见Web安全漏洞深入解析
  • 如何从一款单片机移植到另一款单片机
  • linux创建用户和组、授权、禁止root远程登录、限制SSH的IP登录
  • 10大开源的快速开发平台—架构师必看
  • 3399-9.0 驱动根据vid和pid获取摄像头数量
  • Pandas DataFrame 保存到HTML文件(附炫酷 HTML Table 模板网站)
  • java过滤器(Filter)
  • 概率 | 考研 —— 复习知识点及方法 大总结
  • 【OPC UA】C# 通过OpcUaHelper建立OPC客户端访问KEPServerEx6 OPC服务器数据
  • 【5+】跨webview多页面 触发事件(二)
  • Angular 响应式表单之下拉框
  • Git的一些常用操作
  • iOS帅气加载动画、通知视图、红包助手、引导页、导航栏、朋友圈、小游戏等效果源码...
  • java取消线程实例
  • mongo索引构建
  • Mybatis初体验
  • ng6--错误信息小结(持续更新)
  • Spring声明式事务管理之一:五大属性分析
  • Vue 2.3、2.4 知识点小结
  • vuex 笔记整理
  • 高度不固定时垂直居中
  • 模型微调
  • 浅谈web中前端模板引擎的使用
  • 数据仓库的几种建模方法
  • 微服务框架lagom
  • 【干货分享】dos命令大全
  • 曾刷新两项世界纪录,腾讯优图人脸检测算法 DSFD 正式开源 ...
  • ​如何在iOS手机上查看应用日志
  • ​什么是bug?bug的源头在哪里?
  • ![CDATA[ ]] 是什么东东
  • # Maven错误Error executing Maven
  • #14vue3生成表单并跳转到外部地址的方式
  • #etcd#安装时出错
  • (solr系列:一)使用tomcat部署solr服务
  • (九)c52学习之旅-定时器
  • (一)【Jmeter】JDK及Jmeter的安装部署及简单配置
  • (转)es进行聚合操作时提示Fielddata is disabled on text fields by default
  • (转)linux自定义开机启动服务和chkconfig使用方法
  • (转)setTimeout 和 setInterval 的区别
  • .bat批处理(五):遍历指定目录下资源文件并更新
  • .net core 6 使用注解自动注入实例,无需构造注入 autowrite4net
  • .net framework4与其client profile版本的区别
  • .net mvc部分视图
  • .Net 基于IIS部署blazor webassembly或WebApi
  • .NET处理HTTP请求
  • .net和jar包windows服务部署
  • .NET中GET与SET的用法
  • .php结尾的域名,【php】php正则截取url中域名后的内容
  • /proc/stat文件详解(翻译)