Skip to content

C语言入门

https://akaedu.github.io/book/

  1. 程序的基本概念

    1. 程序和编程语言
    2. 自然语言和形式语言
    3. 程序的调试
    4. 第一个程序
  2. 常量、变量和表达式

    1. 继续Hello World
    2. 常量
    3. 变量
    4. 赋值
    5. 表达式
    6. 字符类型与字符编码
  3. 简单函数

    1. 数学函数
    2. 自定义函数
    3. 形参和实参
    4. 全局变量、局部变量和作用域
  4. 分支语句

    1. if语句
    2. if/else语句
    3. 布尔代数
    4. switch语句
  5. 深入理解函数

    1. return语句
    2. 增量式开发
    3. 递归
  6. 循环语句

    1. while语句
    2. do/while语句
    3. for语句
    4. break和continue语句
    5. 嵌套循环
    6. goto语句和标号
  7. 结构体

    1. 复合类型与结构体
    2. 数据抽象
    3. 数据类型标志
    4. 嵌套结构体
  8. 数组

    1. 数组的基本概念
    2. 数组应用实例:统计随机数
    3. 数组应用实例:直方图
    4. 字符串
    5. 多维数组
  9. 编码风格

    1. 缩进和空白
    2. 注释
    3. 标识符命名
    4. 函数
    5. indent工具
  10. gdb

    1. 单步执行和跟踪函数调用
    2. 断点
    3. 观察点
    4. 段错误
  11. 排序与查找

    1. 算法的概念
    2. 插入排序
    3. 算法的时间复杂度分析
    4. 归并排序
    5. 线性查找
    6. 折半查找
  12. 栈与队列

    1. 数据结构的概念
    2. 堆栈
    3. 深度优先搜索
    4. 队列与广度优先搜索
    5. 环形队列
  13. 本阶段总结


第 1 章 程序的基本概念

目录

  1. 程序和编程语言
  2. 自然语言和形式语言
  3. 程序的调试
  4. 第一个程序

1.1程序和编程语言

计算机只能对数字进行运算,要想计算机处理多种格式的数据,就需要通过一定方法把数据转换为数字。

程序进行符号运算的背后也是转换成数字。

程序由一系列指令(instruction)组成,指令是指示计算机做某种运算的命令,通常包括以下几类:

  • 输入(Input)
    • 从外部设备输入信息到计算机
  • 输出(Output)
    • 输出数据到屏幕,存入文件,发送到其他设备
  • 基本运算
    • 执行最基本的算术运算(加减乘除)和数据存取
  • 测试和分支
    • 条件语句的筛选
  • 循环
    • 重复执行

所有程序都是以上指令混合而成的结果。程序是复杂的,拆解到上面几种指令层级的过程是复杂的,这就由程序员填补上这个鸿沟。

什么是编写程序?

编写程序就是把复杂的任务分解成子任务,把子任务再分解成更简单的任务,层层分解,直到最后简单得可以用以上指令来完成。

编程语言可分为低级语言和高级语言。机器语言和汇编语言属于低级语言,直接用计算机指令编写程序。C、C++等属于高级语言,用语句编写程序,语句是计算机指令的抽象表示。举例说明:

C语言 a = b + 1;

汇编语言

mov  0x804a01c,%eax
add   $0x1,%eax
mov  %eax,0x804a018

机器语言

a1 1c a0 04 08
83 c0 01
a3 18 a0 04 08

这里的机器语言全部由16进制表示。汇编语言时期引入了助记符,到了C语言就进一步简化人的阅读代码的难度。

从汇编语言到机器语言的翻译,由汇编器完成,这里的操作只是简单的替换。

而C语言这里就不是这样,C语言的语句到机器语言的转换没有直观的联系。一条语句要翻译成三条汇编或机器指令,这个过程称为编译(Compile),由编译器完成。

编译需要时间,而这只是高级语言的不起眼的缺点,使用高级语言的好处有很多,最明显的好处就是人可以读懂代码。

其次,C语言是可移植的或者称为平台无关的。

平台可以有以下几种解释:

  • 计算机体系结构
  • 操作系统
  • 开发平台(编译器、链接器)

使用C语言写程序,之后使用不同平台的C编译器,就能把C语言编译成能在不同平台运行的可执行文件。

用C语言写驱动程序是根据特定的平台写的。无法做到平台无关。

编译和解释语言。

习题

1、解释执行的语言相比编译执行的语言有什么优缺点?

优点:

  • 通俗易懂,符合人的直觉
  • 不需要编译步骤,节省时间
  • 执行语句时,就像直接执行命令一样

缺点:

  • 不容易扩展成大型应用
  • 出错时不容易排查

1.2自然语言和形式语言

语法(Syntax)规则由符号(Token)和结构(Structure)的规则构成。结构指Token的排列方式

关于Token的规则称为词法(Lexical)规则,而关于结构的规则称为语法(Grammar)规则。Syntax和Grammar通常都翻译成“语法”,这让初学者非常混乱,Syntax的含义其实包含了Lexical和Grammar的规则,还包含一部分语义的规则,例如在C程序中变量应先声明后使用。

在阅读一个自然语言的句子或者一种形式语言的语句时,搞懂Token的意思只是第一步,还要明白句子/语句是如何由Token构成的,亦即结构。

这个分析句子结构的过程就被称为解析(Parse)。

The other shoe fell.

形式语言和自然相比有哪些异同点?

相同点:

  • Token
  • 结构
  • 语义

不同点:

  • 形式语言的语句有明确含义、设计清晰
  • 形式语言不需要冗余部分

诗歌、说明文和程序的比较

阅读程序的建议(或者其它形式语言):

  • 多花时间阅读
  • 吸收代码,总结出代码的结构
  • 留意小错误(漏标点)

1.3程序的调试

程序中的错误(Bug)分为哪几类?

  • 编译时错误
  • 运行时错误
  • 逻辑错误和语义错误

调试是编程中最有挑战性的地方。

要时刻注意区分编译时和运行时(Run-time)这两个概念,不仅在调试时需要区分这两个概念,在学习C语言的很多语法时都需要区分这两个概念,有些事情在编译时做,有些事情则在运行时做。

也有一种观点认为,编程和调试是一回事,编程的过程就是逐步调试直到获得期望的结果为止。你应该总是从一个能正确运行的小规模程序开始,每做一步小的改动就立刻进行调试,这样的好处是总有一个正确的程序做参考:如果正确就继续编程,如果不正确,那么一定是刚才的小改动出了问题。

1.4第一个程序

c
#include <stdio.h>

int main(void) {
  printf("Hello, World.\n");
  return 0;
}

使用gcc编译时,加上-Wall输出全部错误信息。

习题

把一个正确的程序改写,通过报错来看错误的原因。

第 2 章 常量、变量和表达式

目录

  1. 继续Hello World
  2. 常量
  3. 变量
  4. 赋值
  5. 表达式
  6. 字符类型与字符编码

2.1继续Hello World

多种注释分情况使用

注释不能嵌套

字符串字面值(String Literal)

C标准规定的转义字符

2.2常量

程序中最基本的元素:常量(Constant)

  • 字符(Character)常量
  • 整数(Integer)常量
  • 浮点数(Floating Point)常量
  • 枚举常量

格式化字符串

注意"5"、'5'、5的区别

2.3变量

也是重要概念

计算机存储器一块命名的空间,存入一个可变值

声明变量、声明函数和声明类型

如果一个变量或函数的声明要求编译器为它分配存储空间——定义(Definition)

C语言中,什么是定义?什么是声明?有何区别,互相之间的关系如何?

浮点型的三种:float、double、long double 单精度浮点、双精度浮点、更高精度浮点

变量命名规则

标识符(identifier):变量名、函数名、宏定义、结构体成员名。

关键字/保留字

理解一个概念不是把定义背下来就行了,一定要理解它的外延和内涵,也就是什么情况属于这个概念,什么情况不属于这个概念,什么情况虽然属于这个概念但一般推荐的做法(Best Practice)是要尽量避免这种情况,这才算是真正理解了。

2.4赋值

变量定义之后,把值存入对应的存储器地址的过程被称为赋值(Assignment)

先声明后定义

变量的定义和赋值一次完成,还有个单独的称呼:初始化(initialization)

初始化是一种特殊的声明,而不是赋值语句