1. 第零三章 • 基础
这本章中,我会带你快速的浏览一遍 C 语言的基本特性(feature)。C 语言的特性非常少,而且语法也相当的简单明了。但是这并不代表 C 语言很简单,有深度的内容绝不会浮于表面。所以,接下来我们将快速地了解一下 C 语言的基础,在后面的章节中再慢慢深入。
本章的目的是让所有的读者位于同一水平线上。C 的新手可以在本章多花一些时间,而已经对 C 有一定程度了解的同学则可以大致浏览一遍或直接跳过本章。
1.1. 程序
C 语言程序是由函数定义和类型定义组成的。
因此一个源文件就是一系列的函数和类型。每个函数都可以调用其他函数或调用自身(递归),可以使用任何已经声明的或内建的数据类型。
你还可以调用其他库提供的函数,使用库中提供的数据类型,这也是 C 中多层级系统的复杂性不断增长的根源。
在前一章中,我们提到,所有的程序都是从 main
函数开始执行的。从 main
函数开始不断地调用越来越多的函数,完成期望的工作。
1.2. 变量
C 中的函数可以拥有多个变量。变量其实就是一个有名字的数据项。
C 中的每个变量都有一个特定的类型。这些类型可能是内建的,也可能是我们自定义的。声明一个新变量的时候,首先需要将类型的名字写在前面,然后紧跟的是变量的名字,你还可以使用 =
给这个变量赋一个初始值。变量的声明是一个语句,在 C 语言中,所有的语句必须由 ;
结尾。
如果要创建一个名为 count
的整数(int
),则可以这样写:
int count;
如果要给 count 赋一个初始值:
int count = 10;
下面列出了 C 语言中一些内建的类型:
类型名 | 描述 | 举例 |
---|---|---|
void |
空类型 | |
char |
单个的字符/字节 | char last_initial = 'H'; |
int |
整数 | int age = 32; |
long |
可以表示更大的数的整数 | long age_of_universe = 13798000000; |
float |
浮点数 | float liters_per_pint = 0.568f; |
double |
精度更高的浮点数 | double speed_of_swallow = 0.01072896; |
1.3. 函数声明
函数是一个针对变量的操作过程,同时可能也会改变当前程序的状态。它接受多个输入值,计算并返回一个输出值。
声明函数时,首先将返回值的类型写在前面,后面紧跟函数的名字,而后的一对圆括号里面包裹函数的输入参数,参数之间用 ,
进行分割。函数体部分紧跟其后,包裹在一对花括号 {}
里,里面包含了函数执行的所有语句,语句之间使用 ;
分隔。return
语句用来结束函数的执行,并返回一个值。
下面的代码演示了一个将两个 int
型变量 x
,y
求和之后并返回的函数写法。
int add_together(int x, int y) {
int result = x + y;
return result;
}
调用函数时,首先写上函数名,然后函数参数紧跟其后,包裹在一对圆括号里,参数之间用逗号分开。比如说,我们调用上面的函数,并将计算结果保存到 added
变量中:
int added = add_together(10, 18);
1.4. 结构体声明
结构体用来声明一个新的类型。它可以将多个变量捆绑在一起。
我们可以使用结构体表示更加复杂的数据类型。例如,为了表示一个二维空间里的点,我们可以创建一个名为 point
的结构体将两个 float
类型的变量 x
,y
绑在一起。我们可以同时使用 struct
和 typedef
来声明一个结构体:
typedef struct {
float x;
float y;
} point;
注意,我们应该将结构体放在所有用到它的函数的上方。这个类型和内建的基本数据类型的用法没有任何区别。获取结构体内部的变量时,需要使用小数点 .
,后面紧跟要获取的变量名:
point p;
p.x = 0.1;
p.y = 10.0;
float length = sqrt(p.x * p.x + p.y * p.y);
1.5. 指针
指针类型是普通类型的变体,只需普通类型的后面添加 *
后缀即可。比如,int*
就是一个 int
类型的指针。在之前的 main
函数的输入参数列表中,我们还见过一个 char**
类型,这是一个 char
类型的指针的指针。
指针是 C 语言的精髓所在,也是 C 语言中比较难理解的知识点,我们会在以后的章节中详细讲解。目前的阶段我们还不会用到指针,所以你只需要知道有这个东西就可以了。
1.6. 字符串
在 C 语言中,字符串由 char*
类型表示。它是由一串字符(char
)组成的,并以一个空终结字符结尾。字符串是 C 语言的一个重要且复杂的部分,我们会在接下来的几章中详细的学习它。
字符串还可以字面量来表示,将要表示的字符串包裹在双引号 "
中就可以了。比如说我们之前用过的 "Hello, world!"
。现在,你只需要记住,只要看到 char*
类型,就当成字符串来看待就可以了。
1.7. 条件分支
条件分支语句可以让程序在只有条件为真的时候才去执行一段代码。
我们使用 if
关键字来声明条件语句,执行条件跟在后面,包裹在一对圆括号里,后面紧跟一对花括号里面包裹着条件为真时执行的代码。if
语句后面可以跟一个 else
语句,包含条件为假时执行的代码。
我们可以使用或操作符(||
)和并操作符(&&
)将多个条件组合在一起。
在条件语句中,凡是不为 0 的结果都是真的。这点需要牢记,因为很多条件测试语句都是以此为依据编写的。
检测 x 是否在 10 到 100 之间的条件语句可以这样写:
if (x > 10 && x < 100) {
puts("x is greater than 10 and less than 100!");
} else {
puts("x is less than 11 or greater than 99!");
}
1.8. 循环
循环可以不断的执行一段代码,直到条件变为假,或者计数完成。
在 C 语言中有两种类型的循环。第一种是 while
循环。while
循环不断地执行一段代码,直到条件为假停止。首先 while
关键字在前,后面紧跟包裹在一对圆括号中的条件语句,最后是包裹在一对大括号中的待执行语句。下面是一个例子:
int i = 10;
while (i > 0) {
puts("Loop Iteration");
i = i - 1;
}
第二种循环是 for
循环,跟 while
的条件语句不同的是,for
循环需要三个以 ;
隔开的表达式:一个初始化语句,一个条件语句和一个递增语句。其中初始化语句在循环开始之前执行;条件语句每次迭代都会判断一次,如果为假,循环就退出了;递增语句在每次迭代的最后执行。for
循环通常用来计数,因为它的表示方法比 while
更加简洁。下面的例子中,我们从 0 递增到 9,每次加 1,共执行了 10 次:
for (int i = 0; i < 10; i++) {
puts("Loop Iteration");
}
1.9. 彩蛋
- 使用
for
循环打印 5 次"Hello, world!"
。 - 使用
while
循环打印 5 次"Hello, world!"
。 - 编写一个函数
Hello
,可以打印 n 次"Hello world!"
,然后在main
函数中调用它。 - 除了变量一节中列出的内建类型,还有哪些呢?
- 除了
>
和<
,还有哪些比较操作符? - 除了
+
和-
,还有哪些算数运算符? +=
运算符是什么?它是如何工作的?do...while
循环是是什么?它是如何工作的?switch
语句是什么?它是如何工作的?break
关键字是用来干嘛的?continue
关键字是用来干嘛的?typedef
关键字的作用是什么?