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语句,程序仍然能终止。但是,许多编译器会产生一条警告信息(因为函数应该返回一个整数,却没有这么做)。2.2.3 语句
语句是程序运行时执行的命令。本书后面的几章(主要集中在第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节)就不以分号结尾。]由于语句可以连续占用多行,有时很难确定它的结束位置,因此用分号来向编译器显示语句的结束位置。但指令通常只占一行,因此不需要用分号结尾。
2.2.4 显示字符串
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");
2.3 注释
我们的pun.c程序仍然缺乏某些重要内容:文档说明。每一个程序都应该包含识别信息,即程序名、编写日期、作者、程序的用途以及其他相关信息。C语言把这类信息放在注释(comment)中。符号/*标记注释的开始,符号*/标记注释的结束。例如:
/* This is a comment */
注释几乎可以出现在程序的任何位置上。它既可以独占一行,也可以和其他程序文本出现在同一行中。下面展示的程序pun.c就把注释加在了程序开始的地方:
/* Name: pun.c */ /* Purpose: Prints a bad pun. */ /* Author: K. N. King */ #include <stdio.h> int main(void) { printf("To C, or not to C: that is the question.\n"); return 0; }
注释还可以占用多行。如果遇到符号/*,那么编译器读入(并且忽略)随后的内容直到遇到符号*/为止。如果愿意,还可以把一串短注释合并成为一条长注释:
/* Name: pun.c Purpose: Prints a bad pun. Author: K. N. King */
但是,上面这样的注释可能难以阅读,因为人们阅读程序时可能不易发现注释的结束位置。因此,单独把*/符号放在一行会很有帮助:
/* Name: pun.c Purpose: Prints a bad pun. Author: K. N. King */
更好的方法是用一个“盒形”格式把注释单独标记出来:
/********************************************************** * Name: pun.c * * Purpose: Prints a bad pun. * * Author: K. N. King * **********************************************************/
有些程序员通过忽略3条边框的方法来简化盒形注释:
/* * Name: pun.c * Purpose: Prints a bad pun. * Author: K. N. King */
简短的注释还可以与程序中的其他代码放在同一行:
int main(void) /* Beginning of main program */
这类注释有时也称作“翼型注释”。