C语言处理系统与程序调试运行

官官方信息技术老师·18 页·深入(追求细节与边界)·0 次浏览·38 天前
编译链接预处理调试gdb

C语言处理系统与调试运行

看完你能说清代码到运行的每一步,并亲手断点调试一个C程序

按 空格/→ 演示下一步

问一句
1 / 18 页

全部页面点击任意一页,跳回舞台从这页播放

编译链接预处理调试gdb

C语言处理系统与调试运行

看完你能说清代码到运行的每一步,并亲手断点调试一个C程序

1第 1 页 · C语言处理系统与调试运行

计算机只认识 0 和 1

上一页我们看到 C 处理系统的全貌。先问个根本问题:你在编辑器里敲的 printf、for,CPU 真能看懂吗?不能——CPU 的电路只认高低电平,也就是 0 和 1,所以代码必须先被翻译成机器指令。

CPU 只认 0 和 1
硬件电路按高低电平工作,只能执行二进制机器指令
源代码是给人写的
printf、变量等符号是为程序员设计的抽象,硬件不识别
翻译由编译器完成
编译器把 .c 文件逐层转换成目标 CPU 的机器指令
把中文信译成英文对应 →源代码编译成机器码

中文信对应源代码,收信人(CPU)只懂英文(机器码)

2第 2 页 · 计算机只认识 0 和 1

什么是 C 语言处理系统

上一页说了,CPU 只认 0 和 1,可你写的都是 human 能读的代码。中间这些翻译、组装的活儿谁干?答案是一套打包好的工具链——C 语言处理系统。

预处理
处理 #include 等指令,把头文件内容真正展开进代码
编译
把 C 源码翻译成当前 CPU 的汇编指令
汇编
把汇编指令转成二进制的目标文件(.o)
链接
把多个目标文件和库函数拼成一个可执行文件
翻译装订流水线对应 →C处理系统

各工位逐级加工,对应预处理→编译→汇编→链接

3第 3 页 · 什么是 C 语言处理系统

程序生成的四个阶段

从源代码到可执行文件,要经过四个阶段的加工,每步输出都是下一步的输入。

1
编辑
程序员编写并保存 .c 源文件,此时只是纯文本,机器无法执行
2
预处理
处理 #include、#define 等指令,展开头文件、替换宏,生成 .i 文件
3
编译
把 C 代码翻译成汇编再生成目标文件 .o,此时是二进制但地址未定
4
链接
把多个目标文件与库函数合并,解析地址引用,最终生成可执行文件
4第 4 页 · 程序生成的四个阶段

完整流程图

从左往右读:一个 .c 文件经过四个阶段,每一步都会产出一个中间文件,最终变成可执行文件。

图解渲染中…
b1:预处理器处理 #include 和 #define,输出仍是文本d1:编译器把高级语言翻译成汇编指令f1:汇编器把汇编翻译成机器码h1:链接器合并多个 .o 和库,补齐函数地址
5第 5 页 · 完整流程图

处理系统有哪些

前面我们知道了从源代码到可执行程序要经过四个阶段。那这些阶段靠什么完成?靠的是一套现成的工具——C 语言处理系统,也就是常说的开发环境。

常见工具
GCC、Clang、MSVC(Visual Studio)、Dev-C++、Code::Blocks 等
编辑
编写和修改源代码,产出 .c 文件
编译
把源代码翻译成机器能执行的目标代码
调试
定位程序中的错误,单步跟踪变量变化
运行
执行程序,验证结果是否符合预期
一体化厨房对应 →处理系统

洗菜、切菜、炒菜、装盘四个环节,厨房都配好了对应工具

6第 6 页 · 处理系统有哪些

不同处理系统的对比

同为 IDE,Dev-C++ 与 VS Code 常被新手混为一谈:一个开箱即用,一个强在灵活配置,各有边界。

Dev-C++
  • 自带 MinGW 编译器,装完即用
  • 单文件界面,菜单一键编译运行
  • 轻量、无插件,功能到此为止
VS Code
  • 仅是编辑器,需手动装编译器
  • 靠插件拼装,配置成本高
  • 可扩展为任意语言开发环境
零基础想立刻跑通第一个程序选 Dev-C++;想长期多语言开发再换 VS Code。
7第 7 页 · 不同处理系统的对比

Dev-C++ 的安装与界面

五步装好 Dev-C++,认识它的三大区域,为写程序做好准备。

1
下载安装包
去官方或可信镜像下载 Dev-C++,避免捆绑软件
2
安装向导
双击运行,一路 Next,注意选英文界面即装好
3
首次启动设置
第一次打开选界面语言和主题,中文可选
4
认识编辑区
中间大片白色区域,代码在这里逐字输入
5
认识输出区与工具栏
下方黑框显示编译运行结果,上方按钮一键编译运行
8第 8 页 · Dev-C++ 的安装与界面

第一个程序的完整操作

从新建文件到看到输出,第一次跑通一个 C 程序只需四步。

1
新建源文件
在 Dev-C++ 中新建空白文件,这就是你写代码的地方
2
保存为 .c
必须带 .c 后缀保存,编辑器才知道按 C 语法处理
3
编译
按 F9,把源码翻译成计算机能执行的 0 和 1
4
运行
按 F10 执行生成的程序,黑窗口里看到输出结果
9第 9 页 · 第一个程序的完整操作

编译报错怎么办

bash

故意写错一个分号,看 gcc 如何一步步把错误指给我们。

代码高亮加载中…

gcc 的报错格式是 文件:行:列: 错误类型:提示第5行缺分号;行号是定位问题的第一线索,改完重跑即验证。

10第 10 页 · 编译报错怎么办

调试是什么

上一页我们编译报错后对着报错信息改代码——那还是靠猜。能不能让程序慢下来,一行一行执行,随时看每个变量的值?这就是调试,它和「直接运行」完全是两种操作。

运行 Run
一口气执行完,只给你最终结果,中间过程全黑盒
调试 Debug
可控速执行:可暂停在某行,逐步推进观察状态
断点
在某行做标记,程序跑到这里自动停下等待检查
单步执行
断点停下后一行行走,同时观察每个变量的实时值
看菜谱做菜对应 →调试程序

直接运行是端上成品,调试是边做边尝每一步的味道

11第 11 页 · 调试是什么

用断点单步调试

断点单步调试四步走,让程序停下来说话。

1
设断点
在可疑代码行号旁点击,程序运行到此会暂停
2
启动调试
点 Debug 按钮,程序运行到断点处停下等待
3
单步执行
点 Next line 逐行走,每次只执行一行
4
观察变量
在 Watch 面板查看变量值,与预期对比找错
12第 12 页 · 用断点单步调试

一个最小 C 程序

c

逐行读完这个最小的 C 程序,看懂头文件、main 函数和返回值各管什么。

代码高亮加载中…

第 1 行交给预处理器;第 3 行是唯一入口 main;第 5 行是具体语句,必须以分号结尾;第 6 行返回 0,echo $? 可见它。

13第 13 页 · 一个最小 C 程序

程序结构的关键角色

上一页的最小程序里,你写过 main、大括号和分号——它们不是随意敲的符号,而是 C 语言的硬性规矩。先看清这几个关键角色各自把守什么关口。

main 是入口
程序从 main 的第一句开始执行,链接器据此定位起点
大括号划边界
一对 {} 圈出函数体的范围,少了它编译器不知函数到哪结束
分号是句号
每条语句以 ; 结尾,编译器靠它切分语句
返回值 0
return 0 告诉操作系统:程序正常结束
大楼正门与房间隔断对应 →main 与大括号

main 是唯一正门,大括号是房间墙,分号是每句话的句读点

14第 14 页 · 程序结构的关键角色

动手改一改

c

改一行、加一行,在 Dev-C++ 里重新编译,看程序输出你自己的内容。

代码高亮加载中…

printf 的双引号内是要显示的文字,\n 表示换行;每条语句以分号结尾。改完按 F11 编译运行,新内容立刻出现在黑窗口里。

15第 15 页 · 动手改一改

自测:程序生成与调试

点击作答

一个 .c 源文件从编写到能运行,中间必须经历的关键步骤是什么?

16第 16 页 · 自测:程序生成与调试

本套图解要点收束

  • ✓源码到可执行文件只走四步:预处理、编译、汇编、链接
  • ✓报错先看编译器第一行提示,别急着乱改
  • ✓断点+单步是看程序「怎么跑」的唯一窗口
  • ✓main 是入口,语句以分号结尾,花括号定边界
  • ✓换 IDE 不换原理,GCC 行为处处一致
延伸主题:内存模型:变量存在哪里Makefile 与多文件编译gdb 命令行调试入门
17第 17 页 · 本套图解要点收束

课后思考

先合上讲义自己想一会儿,再看参考答案——问题值得多琢磨。

1四个阶段里,为什么编辑和编译必须分开?如果写完代码直接一键出结果,会损失什么?

参考答案思路:回顾各阶段职责——编辑生成源码,编译才做语法检查。合并后错误定位会更难,也失去分阶段控制优化的机会。可对照编译报错页的报错信息思考。

2程序不报错但结果不对,断点单步调试该怎么用来缩小怀疑范围?

参考答案思路:报错页只能抓语法错,逻辑错要靠调试。先在怀疑点前设断点,看变量值是否符合预期,再单步推进,把『整段都可能有错』缩小到某一行的假设被推翻为止。

3如果把同样的最小 C 程序交给另一套处理系统(如 GCC 与 MSVC),结果一定完全一样吗?边界在哪?

参考答案思路:标准保证核心语义一致,但不同实现报错信息、优化策略、未规定行为可能有差异。想想哪些写法是『标准管得到的』,哪些是『系统自己说了算的』。

18第 18 页 · 课后思考