APP下载

多课程融合的C 语言课程教学探索

2023-10-26吴家洲

实验室研究与探索 2023年7期
关键词:C语言程序设计编程

吴家洲, 张 胜, 刘 君

(南昌航空大学信息工程学院,南昌 330063)

0 引言

工业软件的发展被列为当前科技攻关最紧急和最迫切的问题之一[1]。C 语言作为基础性的开发软件,同时具备底层和高级语言开发的特性,重要性无可替代。Microsoft Windows、Linux、Apple MacOS 和Google Android等代表性操作系统的大部分代码由C 语言编写,办公软件、数据库和邮件系统等用户级别开发也离不开C 语言。国内外大学大量工科类专业把C 语言作为学生学习程序设计的入门语言,并且对课程教学改革做了很多有益的尝试。计算思维是把待求问题用特定符号描述出来,同时依据模块之间关系建立模型,利用计算机的思维方式对模型自动求解的过程[2]。文献[3]中采用计算思维方式详细描述了C 语言程序中的抽象模块,在EIP 寄存器的控制下实现程序的自动执行。计算思维在课程的理论、实践和线上MOOC教学过程中,都取得了较好的效果[4-6]。随着信息技术的发展,以线上视频和线上测试为基础的翻转课堂在教学中发挥重要作用[7-8]。此外,以学科竞赛和项目驱动为引导的C 语言教学被广泛采用[9-11]。近年来,结合计算机硬件的软件类课程教学越来越受到重视,并且出版了相关教材[12-15]。然而,C语言教学一直存在两个主要问题:①基于语言层面的教学,没有结合支撑程序运行的硬件和操作系统相关理论,侧重于数据结构和算法,对程序运行本质缺乏基本认识,不能深入完整理解代码的执行过程;②对于大一新生,C语言与高中及以前所学知识缺乏延续性,上大学之前绝大部分学生没有经过这方面训练和培训,不具备基本的编程思维。

依据C语言与计算机原理课程的联系,通过微课形式补充计算机基本理论知识,加深学生对C 语言程序执行过程的全面理解。本文采用线上线下的混合教学方法,并增开了简单的嵌入式系统实验,使学生明确程序设计的具体应用。

1 多课程融合的教学内容

与C语言相关的计算机基本理论课程主要包括:嵌入式系统设计、计算机组成原理和计算机控制系统等。计算机组成原理是学习计算机理论的入门课程,介绍了计算机系统的整体结构和各组成模块内容[16];嵌入式系统就是一个微型计算机系统,有自己的硬件结构和操作系统[17-18];计算机控制系统主要讲述的是计算机在控制领域的具体应用。选取计算机组成原理和嵌入式系统(ARM Cortex-M3 内核)两门课中与C语言程序设计相关的内容,制作成微课视频,供学生课外学习,其中的重点内容也会在理论课上详细讲解。教学内容及对应关系如表1 所示,其中,指令的执行过程、存储器映射、寻址方式和栈是C 语言程序设计中重要的理论支撑,是培养学生程序设计能力和编程思维的核心内容。

表1 C语言教学内容及与计算机原理的对应关系

实践性环节,引入了STM32F103 微控制器的基本实验:LED流水灯控制,使学生对C 语言实际应用有初步认识。学生不仅能用C 语言编程进行算法设计,也能进行硬件接口的驱动设计。

2 线上线下混合的教学模式

C语言课程知识点繁多且零散,教学内容前后交叉,再加上补充的计算机原理类知识,显然仅仅通过课堂教学很难完成教学任务。课程采用线上线下混合式的教学方法:课前学生在超星网络教学空间观看微课视频,自学C 语言基本语法和简单的计算机基础知识。理论课以多个小项目为驱动,引导学生综合应用所学语法知识,采用计算思维模拟计算机执行过程来思考和设计程序,培养学生程序设计与分析能力。课后采用线上刷题方式巩固所学知识点,鼓励学生在蓝桥杯设计大赛题库及国内外高校C/C+ +题库进行大量的训练。根据布拉姆教育目标分类理论,听课、看视频和作业训练属于认知的最低层次,是学习知识的最基本要求。想要形成编程思想,必须对大量程序进行分析、归纳和评估。只有不断地经过“调试-修改-再调试-再修改”循环,才能掌握程序设计要点,逐步形成编程思维。多年教学实践也表明,要切实提高学生编程能力,大量的编程训练必不可少。

3 教学案例分析

C语言课程主要教学内容如表1 所示,包括:①程序设计的基本语法;②简单的数据结构与算法设计。由于课程开课时间一般在大一上学期,而计算机组成原理和ARM嵌入式系统体系结构本身就比较复杂,因此采用微课方式补充少量基础的计算机原理知识。使得学生不仅知道C 语言语法规定,还知道为什么要这样规定,这样规定的理论依据是什么。

3.1 程序的执行过程

计算机的中央处理器CPU 不能识别C 语言编写的程序代码,程序需要编译链接转变成二进制机器码才能在硬件上执行。由图1 可知,程序的运行过程为:①从存储器读取指令,将指令解码并生成控制信号,同时,程序计数器PC 自动指向下一个地址;②依据CPU 控制器发出的指令从数据区读取待处理的数据并暂存在CPU 的寄存器中,算术逻辑运算单元ALU按照控制器指令从CPU 寄存器取出数据完成相关的运算,并将计算结果返回给数据区。

图1 程序的执行过程

从程序在硬件上运行过程可以看出:C 代码执行时,将指令代码和数据分别存放在内存的不同位置,CPU从内存中读取数据在ALU中完成计算,并将计算结果返回给数据区;CPU的频率大小影响程序执行的效率,程序执行也离不开操作系统的支持。C 程序代码按照从上到下的顺序执行,是由于程序计数器PC自动指向下一个地址的结果。C语言在语法层面的规定是硬件层实现的体现。

3.2 数据的表示

计算机处理的数据可分为数值型数据和非数值型数据,其发展初期主要是数值计算。计算机硬件由数字逻辑电路组成,只能识别高、低电平。内部机器码由0,1 二进制组成,一般情况下,“0”代表低电平;“1”代表高电平。依据人们对数据认识的先后顺序,介绍常用的正数和负数、整数和小数在计算机内部硬件层的表示,以及简单的整数加减运算过程,逐步培养学生兴趣,强化学生对编程语言的感性认知。

正数的二进制原码、反码和补码是相同的,负数的二进制补码等于反码最低位加1。为了将减法运算转变成加法运算,计算机内部数据都采用补码来表示,最高位为符号位,符号位是“0”表示正数,“1”表示负数,每8 位1 byte。数据的表示有定点数和浮点数两种方式,C 语言中的int 数据的用定点数格式表示,小数点在最后一位后面,实际上就是整数,其格式如图2所示。C语言中float、double float 数据类型常用浮点数表示,普遍采用IEEE754 标准规定的格式。4 byte float数据类型格式如图3 所示。表示的数据值大小为

图2 定点数格式

图3 IEEE754标准规定的浮点数格式

由图2 和3 可见,同样为32 位的int和float数据,在计算机内部的表示形式是不同的,对应数据值的计算方法也不同。因此,不同数据类型相互转换必然存在精度的差异,先定义数据类型再进行数据运算是C语言的特点。

补码的出现解决了计算机中数据减法的问题,计算机内部用加法运算来处理减法计算。在硬件层,通过逻辑与、逻辑非和逻辑或及其组合逻辑电路来实现定点数的运算。例如:十进制整数5 和6 的加法/减法的补码计算过程如图4 所示。浮点数计算与此不同,其计算过程非常复杂。

图4 加/减法运算过程(补码)

由此可见,C 语言中不同数据类型在计算机内部有不同的表示形式,具有不同的存储方式。因此,数据在使用前必须先定义其数据类型,便于系统知道采用哪种格式存储数据、调用数据和数据计算。不同数据之间也不能随意转换,避免造成精度的丢失。

3.3 函数的调用

函数是程序设计的核心内容,程序由各种具有特定功能的函数组成。包括主函数在内,函数调用都采用栈的数据结构来处理。栈是在内存上分配的一段存储区间,只不过这段区间存储的内容满足“先进后出”的原则,即先压入栈的变量后弹出使用。以主函数main()调用子函数为例,说明函数调用与栈的关系,如图5 所示。

图5 函数的调用与栈的关系

当子函数被调用时,系统会给子函数创建一个“栈帧”区域,栈底为高地址,向低地址扩展,并将函数地址压入栈底,即epb(main)地址值存储在栈底指针ebp中;接着,将子函数参数等数据值从高位到低位入栈,入栈数据均为局部变量,栈顶地址由栈顶指针esp存储。调用完成后,esp 指针移动栈底指针ebp 位置,依据栈底指针ebp 存储的返回地址程序返回到主函数,调用完成。

可以看出,系统给子函数分配“栈帧”的存储区域,主函数与子函数之间的参数传递是单向的,不可能是双向的。子函数内部的变量存储在栈中,是局部变量,不能随意改变。栈的机制决定了子函数参数不能改变主函数参数的值。函数调用完成后,子函数依据存储在栈底的子函数地址返回主程序,同时,分配的栈空间被释放。

3.4 指针的应用

指针本身就是硬件层地址在逻辑层的抽象。在计算机硬件结构中并不存在指针,只有地址。实际上,CPU是通过数据的地址读取数据的,这从ARM Cortex-M3 存储器映射完全能体现出来。

图6 为ARM Cortex-M3 存储器到TM2-TM7 定时器映射关系。图的左边是对4 GB(4 =232)存储地址的分配,分为代码区、SRAM区、外部设备、私有外设总线和供应商预留地址区。TM2 定时器起始地址0X40000000 正是左边0.5 GB 外设区的起始地址,外设区的第1 个设备就是TM2 定时寄存器。通过地址0X40000000 就可以访问TM2,实现对TM2 的操作。C语言中对数据的访问同样如此,也是通过地址找到数据,实现对数据的读取和写入。

图6 存储器到TM2-TM7定时器映射关系

图7 为两种寻址方式:直接寻址和间接寻址。依据指令地址直接找到数据的方式为直接寻址,而间接寻址是指由指令地址找到下一级地址,再由下一级地址找到数据的方式。

图7 直接寻址与间接寻址

由此可见,C 语言中的指针只是一种抽象的逻辑概念,它不是具体存在于计算机内部。程序中指针变量存储的是地址,计算机是通过地址实现对数据的访问。

3.5 工程实例

在课程“嵌入式系统设计”中,教学选择的是以ARM Cortex-M3 处理器为核心的32 位微控制器STM32。可以在C语言实训课程中,采用标准函数库的编程方法,通过通用的输入输出GPIO 口实现LED流水灯控制的程序设计。

由图8 可以看出,程序执行的逻辑顺序由硬件电路的连接方式来确定,设置引脚为低电平0 时灯亮,为高电平1 时灯灭。系统函数头文件stm32f10x. h 定义了应用层结构体文件和硬件层芯片引脚的映射关系,供开发者在程序中调用。stm32f10x _ gpio. h 和stm32f10x_rcc.h的用法与此类似。delay. h 是用户自定义延时函数头文件,是两次灯亮之间的间隔时间。led.h是控制引脚置高、低电平时的自定义头文件。

图8 硬件连接图

通过工程实例训练可知,程序设计的目的是为了解决特定的工程问题。采用计算思维方式对工程问题进行抽象,用计算机能够识别的数据类型来描述特定的量,设计一系列函数求解问题。虽然程序设计思维是抽象的,但解决的问题是实际的,多解决具体问题有利于编程思维的形成。程序设计不能简单地记住一些语法规定,其最终目的是为了解决实际的工程问题。

4 结语

工业软件、人工智能和智能制造的发展已上升到国家战略,高新技术产业发展需要大量具有程序设计与分析能力的高层次人才。C语言作为一门专业基础课,编程思维的培养对于专业课程学习至关重要。充分考虑计算机组成及体系结构的难度,教学内容以微课的形式补充程序设计在计算机理论方面浅显易懂的基础知识。利用先进的信息技术,采用翻转课堂和项目驱动的形式线上线下混合式教学。

教学实践表明:多课程融合的教学改革促进了学生对语法规定的深入理解,培养了学生程序设计的认知能力和编程思维,提高了学生编程能力。同时,多课程的引入使得学生更加明确专业和个人的发展方向。课程考核在平均分、最高分和最低分上都有稳步的提高,毕业学生初步具备解决复杂工程问题的能力。

猜你喜欢

C语言程序设计编程
编程,是一种态度
元征X-431实测:奔驰发动机编程
编程小能手
基于Visual Studio Code的C语言程序设计实践教学探索
纺织机上诞生的编程
从细节入手,谈PLC程序设计技巧
基于C语言的计算机软件编程
高职高专院校C语言程序设计教学改革探索
PLC梯形图程序设计技巧及应用
论子函数在C语言数据格式输出中的应用