第 2 章 C 语言概述
2.1 简单的 C 程序示例
- 程序清单 2.1 first.c
#include <stdio.h>
int main(void)
{
int num;
num = 1;
printf("I'm a simple ");
printf("computer\n");
printf("My favorite number is %d because it is first.\n", num);
getchar(); // 防止程序输出一闪而过
return 0;
}
I'm a simple computer
My favorite number is 1 because it is first.
2.2 示例解释
2.2.1 C 程序的组成
一个典型的 C 程序由几个重要的部分组成
-
#include
预处理 -
int main(void)
main()函数总是第一个被调用的函数,即使其他函数写在前面 -
function name( )
其余函数 -
语句
函数的函数体由语句和声明组成,C 语言中有 6 种语句,大多数语句需要分号结尾① 标号语句
② 复合语句
③ 表达式语句:赋值表达式
④ 选择语句
⑤ 迭代语句
⑥ 跳转语句:return语句
2.2.2 程序解释
1. #include 预处理
#include <stdio.h>
相当于把 stdio.h 文件中的所有内容都输入在该行所在的位置,类似 Python 的 import 第三方库,而 stdio.h 文件中就包括了标准的输入输出,比如 printf() 函数就定义在里面。因为有些程序不需要输入输出,所以没有把 stdio.h 内置
2. main()函数
int main(void)
C 程序一定从 main() 函数开始执行(即使别的函数写在前面),int 是函数的返回类型,即整型;main 是函数名,其余函数的名字可以变,但是 main 函数名不可以变;() 用于识别其是一个函数,括号内可以存在参数,没有参数就是 void (或者空)。
3. 注释
- 单行注释:
// 这是单行注释
- 多行注释:
/* 这是
多行
注释 */
4. {}—函数体和块
{} 标记函数体的开始和结束,还可以用于把函数中的多条语句合并为一个单元或者块
5. 声明
int num;
在函数中声明一个名为 num 的整型变量,以前要求变量声明在块的顶部,现在不需要
-
命名
① 给变量命名时应使用有意义的变量名或标识符,无法清楚表达意义时,可以加注释。
② 可以用字母、数字和下划线命名,但不能以数字开头,最好也不要以下划线开头(避免与库中的标识符重名)。
③ 避免使用关键字和保留标识符
6. 赋值
num = 1;
6 种基本语句中的赋值表达式语句,即“把值 1 赋给变量 num”
7. printf()函数
printf("I'm a simple ");
printf("computer\n");
printf("My favorite number is %d because it is first.\n", num);
I'm a simple computer
My favorite number is 1 because it is first.
-
printf() 是一个标准函数,用来打印括号内双引号中的内容
-
第二个 printf 中的 \n 并没有打印,转义字符:
\n:换行符,即 Enter 键 \t:制表符,即 Tab 键 \b:退格键,即 Backspace 键
-
第三个 printf 中的 %d 并没有打印,占位符:
- % 提醒程序,要在该处打印一个变量,d 表示把变量作为十进制整数打印
- %d 由后面的变量 num 来代替
- printf() 中的 f 表示一种格式化打印函数
8. return 语句
return 0;
6 种基本语句中的跳转语句,因为函数声明 int main(void) 中 int 表明 main() 函数的返回值应该是一个整数,遗漏 return 语句在程序运行到最外面的右花括号 } 时会返回 0。最好不要遗漏
2.3 简单程序的结构
程序由一个或多个函数组成,必须有 main() 函数。
函数由函数头和函数体组成。
- 函数头:包括函数名、返回类型和传参信息
- 函数体:用 { } 括起来,由一系列 语句 和 声明 组成
#include <stdio.h>
int main(void)
{
//语句 +[声明]
return 0;
}
//(大部分语句都以分号结尾。)
2.4 提高程序可读性
① 有意义的函数名 ② 注释 ③ 用空行分隔成概念上的多个部分 ④ 每条语句各占一行
2.5 进一步使用 C
- 程序清单 2.2 fathm_ft.c
// fathm_ft.c--把 2 音寻转成英寸
#include <stdio.h>
int main(void)
{
int feet, fathoms;
fathoms = 2;
feet = 6 * fathoms;
printf("There are %d feet in %d fathoms!\n", feet, fathoms);
printf("Yes,I said %d feet!\n", 6 * fathoms);
getchar();
return 0;
}
There are 12 feet in 2 fathoms!
Yes,I said 12 feet!
2.5.1 多条声明
一条声明中声明了两个变量,用逗号隔开两个变量(feet 和 fathoms)
int feet, fathoms;
// 等价于
int feet;
int fathoms;
// 不可以这样声明
int feet, int fathoms;
2.5.2 多个打印
printf("There are %d feet in %d fathoms!\n", feet, fathoms);
There are 12 feet in 2 fathoms!
两个 %d ,后面的两个变量用逗号隔开
2.6 多个函数
自己编写新的函数
- 程序清单 2.3 two_func.c
// two_func.c--一个文件中包含两个函数
#include <stdio.h>
// 函数声明
void butler(void);
int main(void)
{
printf("I will summon the butler function.\n");
butler();
printf("Yes. Bring me some tea and writeable DVDs.\n");
getchar();
return 0;
}
// 函数定义
void butler(void)
{
printf("You rang, sir?\n");
}
I will summon the butler function.
You rang, sir?
Yes. Bring me some tea and writeable DVDs.
1. bulter() 函数出现了 3 次
- 第 1 次:函数声明(函数原型),告知编译器在程序中要使用该函数,否则无法运行
- 第 2 次:以 调用函数 的形式出现在 main() 中
- 第 3 次:函数定义
2. 函数执行顺序
- 无论 bulter() 函数定义在 main() 函数前面或者后面,C 程序都是从 main() 函数开始执行
- 惯例都是把 main() 函数定义在前面,其他函数定义在后面(需要在 main() 函数前面声明)
- bulter() 函数何时执行取决于它在 main() 函数中被调用的位置,与定义位置无关
2.7 调试程序
找出程序清单 2.4 中的错误
程序清单 2.4 nogood.c
// nogood.c--有错误的程序
#include <stdio.h>
int main(void)
(
int n, int n2, int n3;
/* 该程序有多处错误
n = 5;
n2 = n * n;
n3 = n2 * n2;
printf("n = %d, n squared = %d, n cubed = %d\n",n, n2, n3)
return 0;
)
2.7.1 语法错误
语法错误是指不遵循 C 语言的规则犯的错误
- main() 函数体用圆括号代替了花括号
- 变量声明错误
int n, int n2, int n3;
// 修改为
int n, n2, n3;
// 或者
int n; int n2; int n3;
- main() 中的注释末尾漏掉了 */,或者用 // 代替 /*
- printf() 语句末尾漏掉了分号
2.7.2 语义错误
语义错误是指语法正确,意思上有错误,即逻辑错误
假设上述代码想要实现 n2 表示 n 的平方,n3 表示 n 的立方
n3 = n2 * n2;
实际代码 n3 表示 n 的四次方
2.7.3 程序状态
1)
语法错误根据编译器的错误提示修改即可
2)
如何跟踪程序,找到语义错误?
- 对于循环次数过多的,可以跟踪一部分循环
- 在关键点插入额外的 printf()
- 调试器(debugger),可以一步一步运行程序,并检查程序变量的值
2.8 关键字和保留标识符
关键字如下表所示,保留标识符包括以下划线字符开头的标识符和标准库函数名,如printf()
auto | extern | short | while |
---|---|---|---|
break | float | signed | _Alignas |
case | for | sizeof | _Alignof |
char | goto | static | _Atomic |
const | if | struct | _Bool |
continue | inline | switch | _Complex |
default | int | typedef | _Generic |
do | long | union | _Imaginary |
double | register | unsigned | _Noreturn |
else | restrict | void | _Static_assert |
enum | return | volatile | _Thread_local |