下面一起来仔细研究一下pun.c程序,并且由此归纳出一些通用的程序格式。简单的C程序一般具有如下形式:
指令 int main(void) { 语句 }
在这个模板以及本书的其他类似模板中,所有以等宽(
Courier
)字体显示的语句都代表实际的C语言程序代码,所有以
中文楷体 + 斜体
显示的部分则表示需要由程序员提供的内容。
注意如何使用花括号来标出
main
函数的起始和结束。C语言使用
{
和
}
的方式非常类似于其他语言中
begin
和
end
的用法。
这也说明了有关C语言一个共识:C语言极其依赖缩写词和特殊符号,这是C程序非常简洁(或者不客气地说含义模糊)的一个原因。
即使是最简单的C程序也依赖3个关键的语言特性:指令(在编译前修改程序的编辑命令)、函数(被命名的可执行代码块,如
main
函数)和语句(程序运行时执行的命令)。下面将详细讨论这些特性。
在编译C程序之前,预处理器会首先对其进行编辑。我们把预处理器执行的命令称为指令。第14章和第15章会详细讨论指令,这里只关注
#include
指令。
程序pun.c由下面这行指令开始:
#include <stdio.h>
这条指令说明,在编译前把
<stdio.h>
中的信息“包含”到程序中。
<stdio.h>
包含C标准输入/输出库的信息。C语言拥有大量类似于
<stdio.h>
的
头
(header,➤15.2节),每个头都包含一些标准库的内容。这段程序中包含
<stdio.h>
的原因是C语言不同于其他的编程语言,它没有内置的“读”和“写”命令。输入/输出功能由标准库中的函数实现。
所有指令都是以字符
#
开始的。这个字符可以把C程序中的指令和其他代码区分开来。指令默认只占一行,每条指令的结尾没有分号或其他特殊标记。
函数 类似于其他编程语言中的“过程”或“子例程”,它们是用来构建程序的构建块。事实上,C程序就是函数的集合。函数分为两大类:一类是程序员编写的函数,另一类则是作为C语言实现的一部分提供的函数。我们把后者称为 库函数 (library function),因为它们属于一个由编译器提供的函数“库”。
术语“函数”来源于数学。在数学中,函数是指根据一个或多个给定参数进行数值计算的规则:
C语言对“函数”这个术语的使用则更加宽松。在C语言中,函数仅仅是一系列组合在一起并且被赋予了名字的语句。某些函数计算数值,某些函数则不是这样。计算数值的函数用
return
语句来指定所“返回”的值。例如,对参数进行加1操作的函数可以执行语句
return x + 1;
而当函数要计算参数的平方差时,则可以执行语句
return y * y – z * z;
虽然一个C程序可以包含多个函数,但只有
main
函数是必须有的。
main
函数是非常特殊的:在执行程序时系统会自动调用
main
函数。在第9章,我们将学习如何编写其他函数,在此之前的所有程序都只包含一个
main
函数。
main
函数的名字是至关重要的,绝对不能改写成
begin
或者
start
,甚至写成
MAIN
也不行。
如果
main
是一个函数,那么它会返回一个值吗?是的。它会在程序终止时向操作系统返回一个状态码。我们再来看看pun.c程序:
#include <stdio.h>
int main(void)
{
printf("To C, or not to C: that is the question.\n");
return 0;
}
main
前面的
int
表明该函数将返回一个整数值。圆括号中的
void
表明
main
函数没有参数。语句
return 0;
有两个作用:一是使
main
函数终止(从而结束程序),二是指出
main
函数的返回值是0。后面还将详细论述
main
函数的返回值(➤9.5节)。
但是现在我们始终让
main
函数的返回值为0,这个值表明程序正常终止。
如果
main
函数的末尾没有
return
语句,程序仍然能终止。但是,许多编译器会产生一条警告信息(因为函数应该返回一个整数,却没有这么做)。
语句
是程序运行时执行的命令。本书后面的几章(主要集中在第5章和第6章)将进一步探讨语句。程序pun.c只用到两种语句:一种是
返回
(
return
)语句,另一种是
函数调用
(function call)语句。要求某个函数执行分派给它的任务称为
调用
这个函数。例如,程序pun.c为了在屏幕上显示一条字符串就调用了
printf
函数:
printf("To C, or not to C: that is the question.\n");
C语言规定每条语句都要以分号结尾。[就像任何好的规则一样,这条规则也有一个例外:后面会遇到的复合语句(➤5.2节)就不以分号结尾。]由于语句可以连续占用多行,有时很难确定它的结束位置,因此用分号来向编译器显示语句的结束位置。但指令通常只占一行,因此 不需要 用分号结尾。
printf
是一个功能强大的函数,第3章会进一步介绍。到目前为止,我们只是用
printf
函数显示了一条
字面串
(string literal)——用一对双引号包围的一系列字符。当用
printf
函数显示字面串时,最外层的双引号不会出现。
当显示结束时,
printf
函数不会自动跳转到下一输出行。为了让
printf
跳转到下一行,必须在要显示的字符串中包含
\n
(
换行符
)。写换行符就意味着终止当前行,然后把后续的输出转到下一行。为了说明这一点,请思考把语句
printf("To C, or not to C: that is the question.\n");
替换成下面两个对
printf
函数的调用后所产生的效果:
printf("To C, or not to C: ");
printf("that is the question.\n");
第一条
printf
函数的调用语句显示出
To C, or not to C
:,第二条调用语句显示出
that is the question.
并且跳转到下一行。最终的效果和前一个版本的
printf
语句完全一样,用户不会发现什么差异。
换行符可以在一个字面串中出现多次。为了显示下列信息:
Brevity is the soul of wit.
--Shakespeare
可以这样写:
printf("Brevity is the soul of wit.\n --Shakespeare\n");