第一周
名词解释
高级语言、低级语言、机器语言
- 高级语言(High-Level Language):
高级语言是一种相对抽象和易于理解的编程语言,其目的是提供更高层次的抽象和功能,使程序员能够更容易地编写复杂的程序。高级语言使用人类可读的语法和结构,使用更高级别的概念和抽象,使得程序的编写更容易、更快速。高级语言通常需要通过编译或解释器转换为机器语言才能在计算机上执行。常见的高级语言包括C、C++、Java、Python和JavaScript等。 - 低级语言(Low-Level Language):
低级语言是与计算机硬件更接近的编程语言,它使用更接近机器语言的语法和结构。低级语言通常直接操作计算机的底层硬件和资源,提供了对硬件细节的更多控制。低级语言可以更高效地利用计算机的资源,但编写和理解低级语言程序相对更困难。汇编语言和机器语言都属于低级语言。 - 机器语言(Machine Language):
机器语言是计算机硬件直接能理解和执行的语言。它由二进制位组成,表示计算机指令和数据。机器语言是计算机可以直接执行的最底层的语言。每个计算机的机器语言是特定于该计算机体系结构的。编写机器语言程序需要对机器指令和二进制表示有深入的了解。由于机器语言的复杂性和难以理解,通常使用高级语言来编写程序,然后通过编译器或解释器将其转换为机器语言。
- 高级语言(High-Level Language):
解释型语言和编译型语

Python 如此设计的原因在于将程序的执行与底层硬件进一步地分离,无需担心程序的编译、汇编以及链接过程,使得 Python 程序相较于 C 程序而言更加易于移植。
C语言源代码到可执行文件的过程
- C源代码:
程序员使用C语言编写源代码,源代码以.c为扩展名。源代码包含了程序的逻辑和功能的定义。 - 预处理:
在编译之前,C预处理器会处理源代码。预处理器执行宏展开、条件编译等操作,生成经过预处理的源代码。 - 编译:
经过预处理的源代gg会被编译器翻译成汇编代码。编译器将C源代码转换为汇编语言表示,生成汇编代码文件(.s文件)。 - 汇编:
汇编器将汇编代码转换为机器码指令。它将汇编代码文件翻译成机器可执行的指令,并生成目标文件(.o文件)。 - 链接:
链接器将目标文件与其他必要的库文件进行链接,生成最终的可执行文件。链接器解析目标文件中的符号引用,并将其与库函数和其他目标文件中的符号定义进行关联。链接器生成一个包含所有必要信息的可执行文件。 - 可执行文件:
最终的可执行文件是操作系统可以直接执行的二进制文件。它包含了程序的机器码指令、数据和其他必要的信息。可执行文件可以通过命令行或操作系统的运行环境来执行。
- C源代码:
静态语言和动态语言
静态语言(Static Language):
静态语言是在编译时进行类型检查的语言。在静态语言中,变量的类型在编译时确定,并且编译器会对类型进行检查。在编译过程中,变量的类型和使用方法需要在代码中明确声明和定义。静态语言的编译器会检查变量的类型是否与其使用方式相匹配,以避免类型错误。常见的静态语言包括C、C++、Java等。优点:
- 更早地发现类型错误,提前检测潜在的编程错误。
- 在编译时进行类型检查,提高代码的稳定性和可靠性。
- 性能较好,由于类型已经确定,编译器可以进行更多的优化。
缺点:
- 代码相对冗长,需要显式声明和定义类型。
- 编译时间较长,需要进行较多的类型检查和编译过程。
动态语言(Dynamic Language):
动态语言是在运行时进行类型检查的语言。在动态语言中,变量的类型可以根据其赋值进行推断,并且可以在运行时动态地改变变量的类型。动态语言的编译器或解释器在运行时进行类型检查和解析。常见的动态语言包括Python、JavaScript、Ruby等。优点:
- 灵活性高,可以在运行时动态地改变变量的类型和行为。
- 代码相对简洁,无需显式声明和定义类型,灵活性提高了开发效率。
缺点:
- 需要在运行时进行类型检查和解析,性能可能相对较低。
- 容易出现运行时类型错误,只能在运行时才能发现。
需要注意的是,静态语言和动态语言并非绝对的对立关系,很多语言在某些方面可以具备静态语言和动态语言的特性。例如,Java是静态语言,但具备一些动态语言的特性,如反射和动态代理。同样,Python是动态语言,但也可以通过类型注解等方式实现静态类型检查。
C语言开发环境
在线运行平台(一键运行):
IDE(集成开发环境):
Visual Studio(一站式安装,一键编译运行)
VSCode + mingw(配置灵活且繁琐,一键编译运行)
Linux环境(vim+gcc)
编译命令
gcc -o 目标文件名 源文件例:
gcc -o test test.c将名为test.c的源文件编译成名为test的目标文件
C语言程序的结构
简单的C程序实例
#include <stdio.h> int main(void) { /* 定义一个名为num的变量 */ int num; /* 为num赋一个值 */ num = 1; /* 使用printf()函数 */ printf("I am a simple "); printf("computer.\n"); printf("My favorite number is %d because it is first.\n", num); return 0; }
#include指令和头文件#include这行代码是一条C预处理器指令。通常,C编译器在编译前会对源代码做一些准备工作,即预处理。#include <stdio.h>的作用相当于把stdio.h文件中的所有内容都输入该行所在的位置。实际上,这是一种“拷贝-粘贴”的操作。main()函数C程序从
main()函数开始执行。除了main()函数,你可以任意命名其他函数,而且main()函数必须是开始的函数。int是main()函数的返回类型。这表明main()函数返回的值是整数。返回到哪里?返回给操作系统通常,函数名后面的圆括号中包含一些传入函数的信息。该例中没有传递任何信息。因此,圆括号内是单词void。//错误的main函数定义1 main() //错误的main函数定义2 void main() //正确的main函数定义1 int main(void) //正确的main函数定义2 int main(int argc, char *argv[])int main(int argc, char *argv[])是C语言中常见的main函数的定义方式,它用于接收命令行参数。参数解释:
int argc:表示命令行参数的数量(Argument Count)。char *argv[]:表示命令行参数的数组(Argument Vector),是一个指针数组,每个指针指向一个以null结尾的字符串,即命令行参数的值。
使用这种方式定义的
main函数可以接收命令行传递的参数,如下所示:#include <stdio.h> int main(int argc, char *argv[]) { printf("argc: %d\n", argc); for (int i = 0; i < argc; i++) { printf("argv[%d]: %s\n", i, argv[i]); } return 0; }运行该程序并传递参数,例如:
./program arg1 arg2 arg3程序运行结果会输出命令行参数的数量以及每个参数的值,如:
argc: 4 argv[0]: ./program argv[1]: arg1 argv[2]: arg2 argv[3]: arg3注释
在程序中,被两个
/* */符号括起来的部分是程序的注释。写注释能让他人(包括自己)更容易明白你所写的程序。C 语言注释的好处之一是,可将注释放在任意的地方,甚至是与要解释的内容在同一行。较长的注释可单独放一行或多行。所有的注释都会被编译器忽略。/* 这是一条C注释。 */ /* 这也是一条注释, 被分成两行。*/ /* 也可以这样写注释。 */ /* 这条注释无效,因为缺少了结束标记。 // 这种注释只能写成一行花括号、函数体和块
花括号把main()函数括起来。一般而言,所有的C函数都使用
花括号标记函数体的开始和结束。这是规定,不能省略。只有花括号({})能起这种作用,圆括号(())和方括号([])都不行。花括号还可用于把函数中的多条语句合并为一个单元或块。声明(declaration)
声明是C语言最重要的特性之一。在该例中,声明完成了两件事。其一,在函数中有一个名为
num的变量(variable)。其二,int表明num是一个整数(即,没有小数点或小数部分的数)。int是一种数据类型。编译器使用这些信息为num变量在内存中分配存储空间。赋值
赋值是C语言的基本操作之一。该行代码的意思是“把值1赋给变量num”。在执行int num;声明时,编译器在计算机内存中为变量num预留了空间,然后在执行这行赋值表达式语句时,把值储存在之前预留的位置。可以给num赋不同的值,这就是num之所以被称为变量(variable)的原因。
printf()函数示例代码中有3行代码都使用了C语言的一个标准函数:
printf()。圆括号表明printf是一个函数名。圆括号中的内容是从main()函数传递给printf()函数的信息。例如,上面的第1行把I am a simple传递给printf()函数。该信息被称为参数。换行符是一个转义序列(escape sequence)。转义序列用于代表难以表示或无法输入的字符。如,\t代表Tab键,\b代表Backspace键(退格键)。每个转义序列都以反斜杠字符(\)开始
return语句return语句是示例程序中的最后一条语句。
int main(void)中的int表明main()函数应返回一个整数。C标准要求main()这样做。有返回值的C函数要有return语句。该语句以return关键字开始,后面是待返回的值,并以分号结尾。如果遗漏 main()函数中的 return 语句,程序在运行至最外面的右花括号(})时会返回0。因此,可以省略main()函数末尾的return语句。但是,不要在其他有返回值的函数中漏掉它。
C语言源程序的书写格式
缩进:使用适当的缩进来表示代码块的层次结构,常见的缩进为4个空格或一个制表符(Tab)。
大括号:对于控制结构、函数等代码块,使用大括号将其括起来,以表示代码块的开始和结束。
if (condition) { // 代码块 // ... }空格:在运算符、逗号、分号等符号周围添加适当的空格,以提高代码的可读性。
int sum = a + b; for (int i = 0; i < n; i++) { printf("%d ", i); }注释:使用注释来解释代码的功能、目的、算法等,以增加代码的可读性和可维护性。
// 计算两个数的和 int sum = a + b;命名规范:使用有意义的变量名、函数名和常量名,遵循命名规范,以提高代码的可读性和可维护性。
int numberOfStudents = 10; void printMessage() { // 函数体 }换行:在较长的语句中,适当地进行换行,以保持代码的可读性。
longResult = (longValue1 + longValue2 + longValue3) / (longValue4 - longValue5);
C语言数据类型
整型(Integer):
int:表示整数类型。通常占用4个字节。short:表示短整数类型。通常占用2个字节。long:表示长整数类型。通常占用4个或8个字节,取决于编译器和操作系统。
示例代码:
int num1 = 10; short num2 = 20; long num3 = 30L; // 后缀L表示长整数类型浮点型(Floating-point):
float:表示单精度浮点数类型。通常占用4个字节。double:表示双精度浮点数类型。通常占用8个字节。
示例代码:
float num1 = 3.14f; // 后缀f表示单精度浮点数类型 double num2 = 2.71828;字符型(Character):
char:表示字符类型。通常占用1个字节。
示例代码:
char ch1 = 'A'; char ch2 = 'B';布尔型(Boolean):
bool:表示布尔类型,只能取true(非零值)或false(零值)。
示例代码:
#include <stdbool.h> // 需要包含stdbool.h头文件 bool flag1 = true; bool flag2 = false;
数据类型示例代码
#include <stdio.h>
#include <stdbool.h>
int main(void) {
// 整型示例
int num1 = 10;
printf("整数num1 = %d,整型大小: %u 字节\n", num1, sizeof(num1));
short num2 = 20;
printf("短整数num2 = %hd,短整数大小: %u 字节\n", num2, sizeof(num2));
long num3 = 30L;
printf("长整数num3 = %ld,长整数大小: %u 字节\n", num3, sizeof(num3));
// 浮点型示例
float num4 = 3.14f;
printf("单精度浮点数num4 = %f,单精度浮点数大小: %u 字节\n", num4, sizeof(num4));
double num5 = 2.71828;
printf("双精度浮点数num5 = %lf,双精度浮点数大小: %u 字节\n", num5, sizeof(num5));
// 字符型示例
char ch1 = 'A';
printf("字符ch1 = %c,字符大小: %u 字节\n", ch1, sizeof(ch1));
char ch2 = 66; // ASCII码值
printf("字符ch2 = %c,字符大小: %u 字节\n", ch2, sizeof(ch2));
// 布尔型示例
bool flag1 = true;
printf("布尔数flag1 = %d,布尔值大小: %u 字节\n", flag1, sizeof(flag1));
bool flag2 = false;
printf("布尔数flag2 = %d,布尔值大小: %u 字节\n", flag2, sizeof(flag2));
return 0;
}
C语言的运算符
C语言中有多种类型的运算符,用于执行各种算术、逻辑和位操作。以下是C语言中常见的运算符类型:
- 算术运算符:用于执行基本的算术操作,如加法、减法、乘法、除法、取模等。
+:加法运算-:减法运算- *:乘法运算
/:除法运算%:取模(取余)运算
- 关系运算符:用于比较两个值之间的关系,返回一个布尔值(1表示真,0表示假)。
==:等于!=:不等于<:小于>:大于<=:小于等于>=:大于等于
- 逻辑运算符:用于执行逻辑操作,对布尔值进行组合和求反。
&&:逻辑与(与)||:逻辑或(或)!:逻辑非(非)
- 位运算符:用于对二进制数据的位进行操作。
&:按位与|:按位或^:按位异或~:按位取反<<:左移>>:右移
- 赋值运算符:用于给变量赋值。
=:简单赋值+=:加法赋值=:减法赋值=:乘法赋值/=:除法赋值%=:取模赋值<<=:左移赋值>>=:右移赋值&=:按位与赋值|=:按位或赋值^=:按位异或赋值
- 自增和自减运算符:用于对变量进行递增或递减操作。
++:自增-:自减
- 条件运算符:用于根据条件选择不同的值。
? ::条件表达式,也称为三元运算符。
- 其他运算符:还有一些其他类型的运算符,如指针运算符、sizeof运算符、类型转换运算符等。