本文为清华大学出版社出版的《C语言入门经典》一书的学习笔记,在此感谢作者及相关人员。本文为原创学习笔记,转载请注明出处,谢谢。
1.1 创建C程序
C程序的创建过程有4个基本步骤或过程:编辑、编译、链接和执行。
1.1.1 编辑
编辑过程就是创建和修改C程序的源代码——我们编写的程序指令称为源代码。
1.1.2 编译
编译器可以将源代码转换成机器语言,在编译的过程中,会找出并报告错误。这个阶段的输入是在编辑期间产生的文件,常称为源文件。
编译器能找出程序中很多无效或无法识别的错误,以及结构错误,例如程序的莫部分永远不会执行。编译器的输出结果称为对象代码(object code),存放它们的文件称为对象文件(object file),这些文件的扩展名在Windows环境中通常是.obj,在Linux/Unix环境中通常是.o。编译器可以在转换过程中找出集中不同类型的错误,他们大都会阻止对象文件的创建。
如果编译成功,就会生成一个文件,它与源文件同名,但扩展名是.o或者.obj。
如果在UNIX系统下工作,在命令行上编译C程序的标准命令是cc(若编译器是GNU‘s Not UNIX(GNU),则命令为gcc),下面是一个示例:
cc -c myprog.c
其中,myprog.c是要变异的程序,如果省略了-c这个参数,程序还会自动链接。成功编译的结果是生成一个对象文件。
大多数C编译器都有标准的编译选项,在命令行(如cc myprog.c)或继承开发环境下的菜单选项(Complie菜单选项)里都可以找到。
1.1.3 链接
连接器(linker)将源代码文件中由编译器产生的各种模块组合起来,再从C语言提供的程序库中添加必要的代码模块,将他们组合成一个可执行的文件。连接器也可以检测和报告错误,例如,遗漏了程序的某个部分,或者引用了一个根本不存在的库组件。
实际上,如果程序太大,可将其拆成几个源代码文件,再用连接器连接起来。因为很难一次编写一个很大的程序,也不可能只使用一个文件。如果将它拆成多个小源文件,每个源文件提供程序的一部分功能,程序的开发就容易多了。这些源文件可以分别编译,更容易避免简单输入错误的发生。再者,整个程序可以一点一点地开发,组成程序的源文件通常会用同一个项目名称集成,则个项目名称用于引用整个程序。
程序库提供的例程可以执行非C语言的操作,从而支持和扩展了C语言。例如,库中包含的例支持输入、输出、计算平方根、比较两个字符串,或读取日期和事件信息等操作。
链接阶段出现错误,意味着必须重新编辑源代码;反过来,如果链接成功,就会产生一个可执行文件。在Window环境下,这个可执行文件的扩展名为.exe;在UNIX环境下,没有扩展名,但它是一个可执行的文件类型。
多数IDE也有Build(建立)选项,它可一次完成程序的编译和链接。在IDE中,这个选项通常在Complie(编译)菜单选项中,一些IDE有单独的Build菜单项。
1.1.4 执行
执行阶段就是当成功完成了前述3个过程后,运行程序。但是,这个阶段可能会出现各种错误,包括输出错误及什么也不做,甚至使计算机崩溃。不管出现哪种情况,都必须返回编辑阶段,检查并修改代码。
在这个阶段,计算机会最终精确地执行指令。在UNIX和Linux下,只要键入编译和链接后的文件名,即可执行程序。在大多数IDE中,都有一个相应的菜单命令,来运行或者执行已编译的程序。在Windows环境中,运行程序的.exe文件即可,这与运行其他可执行程序一样。
1.2 创建第一个程序
/* Program 1.1 Your Very First C Program - Displaying Hello World */
#include
int main(void)
{
printf("Hello World!");
return 0;
}
在输入了上面的源代码后,将程序保存为hello.c。可以使用任意名字替代hello,但扩展名必须是.c。这个扩展名在C语言中是很常见的,它表示文件的内容是C语言源代码。大多数C编译器都要求源文件的扩展名是.c,否则编译器会拒绝处理它。
下面编译、链接、运行该程序。
1.3 编辑第一个程序
1.4 处理错误
1.5 剖析一个简单的程序
/*Program 1.3 Another Simple C Program - Displaying a Quotation */ #include1.5.1 注释int main(void) { printf("Beware the Ides of March!"); return 0; }
上述代码第一行,这不是程序代码,因为它没有告诉电脑执行操作,它只是一行注释。位于/*和*/之间的任意文本都是注释。/*和*/可以放在同一行代码上,也可以放在不投行代码上。
1.5.2 预处理指令
下面这行代码
#include
严格来说,它不是可执行程序的一部分,但它很重要,事实上程序没有它是不执行的。符号#表示这是一个预处理指令(preprocessing derective),告诉编译器在编译源代码之前,要先执行一些操作。编译器在编译过程开始之前的预处理阶段处理这些指令。预处理指令相当多,大度搜狐放于程序源文件的开头。
在这个例子中,编译器要将stdio.h文件的内容包含进来,这个文件成文头文件(header file),因为它通常放在程序的开头处。在本例中,头文件定义了C标准库函数中一些函数的信息,但一般情况下,头文件指定的信息应由编译器用于在程序中集成预定义函数或其他全局对象,所以有时需要创建自己的头文件,以用于程序。
注意:头文件名是不区分大小写的,但在#include指令里,这些文件名通常是小写。
1.5.3 定义main函数
下面五行指令定义了main()函数
int main(void)
{
printf("Beware the Ides of March!");
return 0;
}
函数是两个括号之间执行某组操作的一段代码。每个C程序都由一个或多个函数组成,每个C程序都必须有一个main()函数——因为每个程序总是从这个函数开始执行。
1.5.4 关键字
在C语言中,关键字是有特殊意义的字,所以在程序中不能将关键字用于其他目的。关键字也称保留字,在前面的例子里,int就是一个关键字,void和return也是关键字。附录C列出了完整的C语言关键字表。
1.5.5 函数体
函数体是在函数名称后面位于其实及结束两个大括号之间的代码块。它包含了定义函数功能的所有语句。
每个函数必须有函数体,但函数体可以是空的,仅有起始及结束两个大括号,里面没有任何语句,在这种情况下,这个函数什么也不做。
这样的函数有什么用?事实上,在开发一个包含很多函数的程序时,这种函数是非常有用的。我们可以声明一些用来解决手头问题的空函数,确定需要完成的编程工作,再为每个函数创建程序代码。这个方法有助于调理分明地、系统地建立程序。
1.5.6 输出信息
例子中的main函数体包含了一个调用prinft()函数的语句:
printf("Beware the Ides of March!");
printf()是一个标准的库函数,它将引号内的信息输出到屏幕上,在这个例子里,调用这个函数会显示引号内的一段警示语。
1.5.7 参数
包含在函数名后的圆括号内的项称为参数,它指定要传给函数的数据。当传送给函数的参数多于一个时,要用逗号分开。
1.5.8 控制符
反斜杠(\)在字符串里有特殊意义,它表示转移序列的开始。转移序列可以在字符串中插入无法指定的字符,例如制表符及换行,或编译器在某些情况下会混淆的字符,例如双引号。反斜杠后边的字符表示是那种转义序列。显然,反斜杠是有特殊意义的,所以需要一种方式在字符串中指定反斜杠。为此,应使用两个反斜杠(\\)。详细请参照转义序列表。
1.6 用C语言开发程序
1.6.1 了解问题
1.6.2 详细设计
1.6.3 实施
1.6.4 测试
1.7 函数及模块化编程。
大多数编程语言都提供了一种方法,将层序切割成多个段,各段都可以独立编写。在C语言中,这些段称为函数。一个函数的程序代码可以与其他函数时相互隔绝的。函数与外界有一个特殊的接口,可将信息传进来,也可以将函数产生的结果传出去。这个接口在函数的第一行即在函数名的地方指定。
将程序分割成多个易于管理的小单元,对编程是非常重要的,其理由如下:
1)可以单独编写和测试每个函数,大大简化了使整个程序运转起来的过程。
2)几个独立的小函数比一个大函数更容易处理和理解。
3)库就是提供人使用的函数集。因为它们是实现写好,且经过测试,能正常工作,所以可以放心地使用,无需细究它的代码细节。这就加快了开发程序的速度,因为我们只需关注自己的代码,这是C语言的一个基本组成部分。C语言中丰富的函数库大大增强了C语言的能力。
4)也可以编写自己的函数库,应用于自己感兴趣的程序类型。如果发现经常编写某个函数,就可以编写它的通用版本以满足自己的需求,并将它加入自己的库中。以后需要用到这个函数时,就可以使用它的库版本了。
5)在开发包含几千到几百万行代码的大型程序时,可以由一些程序设计团队来进行,每个团队负责一个指定的函数子组,最后把它们组成完整的程序。
1.8 常见错误
1.9 要点
1.10 小结
本章编写了几个C程序,我们学习了许多基础知识,本章的重点是介绍一些基本概念,而不是详细探讨C程序语言。现在读者应该对编写、编译及链接程序很有信心了。也许读者目前对如何构建C程序只有模糊的概念。以后学了更多的C语言知识,编写了一些程序后,就会清楚明白了。