CS61c系列课程学习
本系列博客的分享是基于《CS61c》这门课程进行,主要记录的是我在学习期间的心得和收获。
引言
工欲善其事,必先利其器。——《论语·卫灵公》
我要学计算机体系结构,为什么要学C语言?讲体系结构的课程为什么会在一开始先讲解C语言呢?因为C语言有指针的用法,可以直接操纵内存。而计算机体系结构的一个非常重要的概念,就是内存,在内存中存储数据以及加载数据到内存中。换句话说,C语言是比较底层的,在高级语言中,可以用C语言来窥探体系结构的奥秘。
正文
一、C语言的编译
C语言的编译,是与计算机所选用的体系结构有关的。
就像是用x86编译的C程序,没有办法在RISC-V的架构上运行。
C语言的编译过程:
- C compilers map C programs directly into architecture-specific machine code (string of 1s and 0s).
- For C,generally a two part process of compiling .c files to .o files, then linking the o.files into executables.
- 如图所示:
C编译的优势
1、Reasonable compilation time:
- enhancements in compilation procedure (Makefiles) allow only modified files to be recompiled.
2、Excellent run-time performance:
- generally much faster than Scheme or Java for comparable code.
- (because it optimizes for a given architecture)
其实用英文已经可以非常好的表达出 编译的基本概念 了,让我用最经典的三段论总结一下
- 是什么:C语言程序 映射为 与体系结构相关的机器码(一堆0和1)
- 怎么做:将.c文件编译成.o文件,然后再将这些.o文件链接起来,组成可执行文件。
- 为什么: 编译时间合理、运行时性能更好
C语言编译的缺点:
- 移植困难:在新的指令集架构上需要重构代码
- 迭代慢:“Change -> Compile -> Run”的更新周期慢
二、C语言的预处理
1、预处理的时机
预处理(C Pre-Processor, CPP),在C语言的编译之前。如图所示:
2、预处理对源代码做什么
- 用空格取代注释
- 复制-粘贴 (文本替换)
3、预处理的用法
预处理的命令以#
开头,最常用的如下:
#include "file.h" // 头文件
#include <stdio.h> // 头文件
#define PI (3.14159) // 宏
#if / #endif // 条件编译预处理
#include "file.h"
代表,预处理时会优先寻找当前目录下的文件file.h
#include <stdio.h>
代表,预处理时可以直接去C语言的库中寻找<stdio.h>
#define PI (3.14159)
是定义宏,宏就是最简单的复制粘贴。可以通过宏定义一个常量,也可以通过宏定义一个“函数”#if / #endif
是一对条件编译预处理的关键字。
4、如何看预处理生成什么内容
在编译的时候, 在gcc
命令后加上-save-temps
。
实例分析:
- 创建一个
main.c
文件,代码如下:
#include <stdio.h>
#define PI (3.14159)
int main(){
printf("PI = %f\n",PI);
return 0;
}
- 执行命令:
gcc -o main -save-temps main.c
-o main
是一个整体,用于产生最终的执行文件,名字为“main”
-save-temps
的意思就是,保存编译产生的所有临时文件 - 产生了
main main.c main.i main.o main.s
这五个文件
其中,main.i
就是预处理之后产生的文件,可以简单看一下。
对于宏的应用,在这里多说一点。
- 宏可以用来定义一个常数,例如
# define PI (3.14159)
.而在C语言中,
也有另一种方法定义常数:关键字`const``,这个关键字就表示创建一个变量,但是不要改变他。 - 宏也可以定义一个函数,宏定义的函数与一般定义的函数有什么区别呢?
宏定义的函数相当于是复制粘贴,是最简单快捷的文本替换,没有时间开销,编译器都不会看到你定义的宏,在预处理阶段就已经把文本复制过来了。但是普通的函数,在使用的时候会有调用的时间,也就是说,会有额外的时间去花费在函数的调用上。
三、C语言的简单语法
1、main
函数
语法:
int main(int argc, char *argv[])
argc
will contain the number of strings on the command line.
- The executable counts as one, plus one for each argument.
- 从零开始,可执行文件是
argc
的第0个元素argv
is a pointer to an array containing the arguments as strings.
argc
与argv
的理解
argc
是在命令行中字符串的数量,可执行文件也算数,计数从0开始。argv
是一个指向 包含命令行参数的 数组 的指针。
2、int
在遇到想用
int
的时候,可以考虑用intN_t
或intN_t
.
(N是一个整数,例如32,即int32_t
)。
3、 const
Constant is assigned a typed value once in the declaration; value can’t change during entire execution of program.
例如:const int days_in_week = 7;
- 在定义变量前面加上
const
关键字,之后就不能改变这个变量里的值了。
4、enum
Enums: a group of related integer constants.
例如:enum color {RED, GREEN, BLUE};
- 使用枚举可以让代码变得易读。
5、typedef
Typedef allows you define new types.
typedef uint8_t BYTE; BYTE b1,b2;
6、struct
Structs are structured groups of variables.
typedef struct { int length_in_seconds; int year_recorded; } SONG; SONG song1; song1.length_in_seconds = 213; song1.year_recorded = 1994;
7、do-while
语法
do {statement} while(expression);
总结
本文根据CS61C的课程内容,根据自己的理解,简要总结了C语言的编译、预处理与简单语法这三部分的内容。由于刚刚学,难免有理解偏差的地方,希望大家批评指正!