C 基础(2) - C 语言概述
这篇文章详细讲解了一个简单C语言程序的结构和组成要素。首先通过一个示例程序引入,逐行解释了#include指令、main()函数、注释、花括号、变量声明、赋值语句、printf()函数和return语句的作用。接着分析了C程序的基本结构,包括函数头、函数体以及语句和声明的组成。然后通过一个包含多个函数的示例,说明了函数原型、函数调用和函数定义的概念。最后列出了C语言的关键字,并总结了C程序的基本组
1. 简单的C 程序示例
1.1 示例解释

1.2 快速概要
本节简述程序中的每行代码的作用。下一节详细讨论代码的含义。
#include<stdio.h> ←包含另一个文件
该行告诉编译器把 stdio.h 中的内容包含在当前程序中。stdio.h是C 编译器软件包的标准部分, 它提供键盘输入和屏幕输出的支持。
int main (void) ←函数名
C程序包含一个或多个函数,它们是C程序的基本模块。程序清单 2.1 的程序中有一个名为 main()的 函数。圆括号表明 main()是一个函数名。int 表明 main()函数返回一个整数, void 表明 main()不带 任何参数。这些内容我们稍后详述。现在,只需记住 int 和 void 是标准 ANSI C 定义 main()的一部分(如 果使用 ANSIC 之前的编译器,请省略 void;考虑到兼容的问题,请尽量使用较新的C编译器)。
/* 一个简单的C程序 */ 注释
注释在/*和*/两个符号之间,这些注释能提高程序的可读性。注意,注释只是为了帮助读者理解程序, 编译器会忽略它们。
{ ←函数体开始
左花括号表示函数定义开始,右花括号(})表示函数定义结束。
int num; 声明
该声明表明,将使用一个名为 num 的变量,而且num 是 int (整数)类型。
num = 1; ←赋值表达式语句
语句 num = 1;把值 1赋给名为 num 的变量。
printf("I am a simple "); ←调用一个函数
该语句使用 printf()函数,在屏幕上显示 I am a simple,光标停在同一行。printf()是标准 的C库函数。在程序中使用函数叫作调用函数。
printf("computer.\n"); ←调用另一个函数
接下来调用的这个printf()函数在上条语句打印出来的内容后面加上“computer”。代码\n 告诉计 算机另起一行,即把光标移至下一行。
printf("My favorite number is %d because it is first.\n", num);
最后调用的printf()把num 的值(1)内嵌在用双引号括起来的内容中一并打印。%d 告诉计算机以 何种形式输出 num 的值,打印在何处。
return 0; return语句
C函数可以给调用方提供(或返回)一个数。目前,可暂时把该行看作是结束 main()函数的要求。
} 结束
必须以右花括号表示程序结束。
1.3 程序细节
我们来仔细分析这个程序。再次强调,本节将逐行分析程序中的代码,以每行 代码为出发点,深入分析代码背后的细节,为更全面地学习C语言编程的特性夯实基础。
1. #include 指令和头文件
#include<stdio.h>
这是程序的第1行。#include 的作用相当于把stdio.h 文件中的所有内容都输入该行所在的位置。实际上,这是一种“拷贝-粘贴”的操作。 include 文件提供了一种方便的途径共享许多程 序共有的信息。
#include 这行代码是一条C预处理器指令(preprocessor directive)。通常,C编译器在编译前会对源 代码做一些准备工作,即预处理(preprocessing)。
所有的C编译器软件包都提供stdio.h 文件。该文件中包含了供编译器使用的输入和输出函数(如, printf())信息。该文件名的含义是标准输入/输出头文件。通常,在C程序顶部的信息集合被称为头文 件(header)。
在大多数情况下,头文件包含了编译器创建最终可执行程序要用到的信息。例如,头文件中可以定义 一些常量,或者指明函数名以及如何使用它们。但是,函数的实际代码在一个预编译代码的库文件中。简 而言之,头文件帮助编译器把你的程序正确地组合在一起。
ANSI/ISO C规定了C编译器必须提供哪些头文件。有些程序要包含 stdio.h,而有些不用。特定C 实现的文档中应该包含对C库函数的说明。这些说明确定了使用哪些函数需要包含哪些头文件。例如,要 使用 printf() 函数,必须包含stdio.h头文件。省略必要的头文件可能不会影响某一特定程序,但是最 好不要这样做。本书每次用到库函数,都会用#include 指令包含 ANSI/ISO 标准指定的头文件。
2. main ()函数
int main (void);
void main()
程序清单 2.1 中的第2行表明该函数名为 main。的确,main 是一个极其普通的名称,但是这是唯一 的选择。C 程序一定从 main() 函数开始执行(目前不必考虑例外的情况)。除了 main()函数,你可以任意命名其他函数,而且main()函数必须是开始的函数。圆括号有什么功能?用于识别 main()是一个函数。 很快你将学到更多的函数。就目前而言,只需记住函数是C程序的基本模块。
int 是 main()函数的返回类型。这表明 main()函数返回的值是整数。返回到哪里?返回给操作系统。
通常,函数名后面的圆括号中包含一些传入函数的信息。该例中没有传递任何信息。因此,圆括号内 是单词 void
如果浏览旧式的代码,会发现程序以如下形式开始:
main()
C90 标准勉强接受这种形式,但是C99和C11 标准不允许这样写。因此,即使你使用的编译器允许, 也不要这样写。
你还会看到下面这种形式:
void main()
一些编译器允许这样写,但是所有的标准都未认可这种写法。因此,编译器不必接受这种形式,而且
许多编译器都不能这样写。需要强调的是,只要坚持使用标准形式,把程序从一个编译器移至另一个编译 器时就不会出什么问题。
3. 注释
/*一个简单的程序*/
在程序中,被/**/两个符号括起来的部分是程序的注释。写注释能让他人(包括自己)更容易明白你 所写的程序。C 语言注释的好处之一是,可将注释放在任意的地方,甚至是与要解释的內容在同一行。较 长的注释可单独放一行或多行。在/*和*/之间的内容都会被编译器忽略。下面列出了一些有效和无效的注 释形式:
/* 这是一条C注释。 */
/* 这也是一条注释,
被分成两行。*/
*/
也可以这样写注释
*/
/* 这条注释无效,因为缺少了结束标记。
C99 新增了另一种风格的注释,普遍用于C++和Java。这种新风格使用//符号创建注释,仅限于单行。
// 这种注释只能写成一行。
int rigue; // 这种注释也可置于此。
因为一行末尾就标志着注释的结束,所以这种风格的注释只需在注释开始处标明//符号即可。
4. 花括号、函数体和块
{
......
}
程序清单 2.1 中,花括号把 main()函数括起来。一般而言,所有的C 函数都使用花括号标记函数体的 开始和结束。这是规定,不能省略。只有花括号({})能起这种作用,圆括号(())和方括号([])都 不行。
花括号还可用于把函数中的多条语句合并为一个单元或块。如果读者熟悉 Pascal、ADA、Modula-2 或 者 Algol,就会明白花括号在C语言中的作用类似于这些语言中的 begin 和 end。
5. 声明
int num;
这行代码叫作声明(declaration)。声明是C语言最重要的特性之一。在该例中, 声明完成了两件事。其一,在函数中有一个名为 num 的变量(variable)。其二, int 表明 num 是一个 整数(即,没有小数点或小数部分的数)。int 是一种数据类型。编译器使用这些信息为num 变量在内 存中分配存储空间。分号在C语言中是大部分语句和声明的一部分,不像在Pascal 中只是语句间的分 隔符。
在C语言中,所有变量都必须先声明才能使用。这意味着必须列出程序中用到的所有变量名及其类型。
以前的C语言,还要求把变量声明在块的顶部,其他语句不能在任何声明的前面。C99 和C11 遵循 C++的惯例,可以把声明放在块中的任何位置。尽管如此,首次使用变量之前一定要 先声明它。
数据类型
C语言可以处理多种类型的数据,如整数、字符和浮点数。把变量声明为整型或字符类型,计算机才 能正确地储存、读取和解释数据。
命名
给变量命名时要使用有意义的变量名或标识符(如,程序中需要一个变量数羊,该变量名应该是 sheep_count 而不是x3)。如果变量名无法清楚地表达自身的用途,可在注释中进一步说明。这是一种良 好的编程习惯和编程技巧。
可以用小写字母、大写字母、数字和下划线()来命名。而且,名称的第1个字符必须是字符或下划 不能是数字。
C语言的名称区分大小写,即把一个字母的大写和小写视为两个不同的字符。因此,stars 和 Stars、 STARS 都不同。
6. 赋值
num = 1;
程序清单中的这行代码是赋值表达式语句。赋值是C语言的基本操作之一。该行代码的意思是“把值 1赋给变量 num”。在执行 int num;声明时,编译器在计算机内存中为变量 num 预留了空间,然后在执行 这行赋值表达式语句时,把值储存在之前预留的位置。可以给 num 赋不同的值,这就是 num 之所以被称为 变量(variable)的原因。注意,该赋值表达式语句从右侧把值赋到左侧。另外,该语句以分号结尾
7. printf()函数
printf("I am a simple ");
printf("computer.\n");
printf("My favorite number is d because it is first.\n", num);
这3行都使用了 C语言的一个标准函数: printf()。圆括号表明 printf 是一个函数名。圆括号中 的内容是从 main()函数传递给 printf()函数的信息。例如,上面的第1行把I am a simple 传递给 printf()函数。该信息被称为参数,或者更确切地说,是函数的实际参数(actual argument),如图2.3所 示。(在C语言中,实际参数(简称实参)是传递给函数的特定值,形式参数(简称形参)是函数中用于储 存值的变量。第5章中将详述相关内容。) printf() 函数用参数来做什么?该函数会查看双引号中的内容, 并将其打印在屏幕上。

8. return 语句
return 0;
return 语句是程序清单2.1的最后一条语句。int main (void)中的int 表明 main()函数应返回 一个整数。C标准要求 main() 这样做。有返回值的C函数要有 return 语句。该语句以 return 关键字 开始,后面是待返回的值,并以分号结尾。如果遗漏 main()函数中的 return 语句,程序在运行至最外 面的右花括号(})时会返回0。因此,可以省略 main()函数末尾的 return 语句。但是,不要在其他有 返回值的函数中漏掉它。因此,强烈建议读者养成在 main()函数中保留 return 语句的好习惯。在这种 情况下,可将其看作是统一代码风格。但对于某些操作系统(包括 Linux 和 UNIX), return 语句有实际 的用途。
2. 简单的程序结构
在看过一个具体的程序示例后,我们来了解一下C 程序的基本结构。程序由一个或多个函数组成,必 须有 main() 函数。函数由函数头和函数体组成。函数头包括函数名、传入该函数的信息类型和函数的返 回类型。通过函数名后的圆括号可识别出函数,圆括号里可能为空,可能有参数。函数体被花括号括起来, 由一系列语句、声明组成,如图2.4所示。本章的程序示例中有一条声明,声明了程序使用的变量名和类型。 然后是一条赋值表达式语句,变量被赋给一个值。接下来是3条 printf() 语句,调用 printf()函数3 次。最后,main()以return 语句结束。

3. 多个函数
到目前为止,介绍的几个程序都只使用了 printf()函数。程序清单 2.3 演示了除 main () 以外,如何 把自己的函数加入程序中。
//* two_func.c -- 一个文件中包含两个函数 */
#include <stdio.h>
void butler (void); /* ANSI/ISO C*/
int main(void)
{
printf("I will summon the butler function.\n");
butler() ;
printf("Yes. Bring me some tea and writeable DVDs.\n") ;
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.
butler()函数在程序中出现了3次。第1次是函数原型(prototype),告知编译器在程序中要使用该函数:第2次以函数调用(function call)的形式出现在 main()中;最后一次出现在函数定义(function definition)中,函数定义即是函数本身的源代码。下面逐一分析。
C90 标准新增了函数原型,旧式的编译器可能无法识别(稍后我们将介绍,如果使用这种编译器应该 怎么做)。函数原型是一种声明形式,告知编译器正在使用某函数,因此函数原型也被称为函数声明 (function declaration)。函数原型还指明了函数的属性。例如,butler()函数原型中的第1个 void 表明, butler () 函数没有返回值(通常,被调函数会向主调函数返回一个值,但是 bulter ()函数没有)。第2个void (butler (void) 中的 void)的意思是 butler() 函数不带参数。因此,当编译器运行至此,会检查 butler ()是否使用得当。注意, void 在这里的意思是“空的”,而不是“无效”。
早期的C语言支持一种更简单的函数声明,只需指定返回类型,不用描述参数:
void butler():
早期的代码中的函数声明就类似上面这样,不是现在的函数原型。C90、C99 和 C11 标准都承认旧 版本的形式,但是也表明了会逐渐淘汰这种过时的写法。如果要使用以前写的C代码,就需要把旧式声明 转换成函数原型。本书在后面的章节会继续介绍函数原型的相关内容。
接下来我们继续分析程序。在main() 中调用 butler () 很简单,写出函数名和圆括号即可。当 butler() 执行完毕后,程序会继续执行 main()中的下一条语句。
程序的最后部分是 butler()函数的定义,其形式和 main () 相同,都包含函数头和用花括号括起来 的函数体。函数头重述了函数原型的信息: bulter() 不带任何参数,且没有返回值。如果使用老式编译器, 请去掉圆括号中的void.
这里要注意,何时执行 butler()函数取决于它在 main() 中被调用的位置,而不是 butler()的定义在文件中的位置。例如,把 butler()函数的定义放在 main()定义之前,不会改变程序的执行顺序, butler ()函数仍然在两次 printf() 调用之间被调用。记住,无论 main()在程序文件处于什么位置,所 有的C程序都从 main()开始执行。但是,C的惯例是把main()放在开头,因为它提供了程序的基本框架。
C标准建议,要为程序中用到的所有函数提供函数原型。标准 include 文件(包含文件)为标准库函 数提供可函数原型。例如,在C标准中,stdio.h文件包含了printf()的函数原型。
4. 关键字和保留标识符
关键字是C语言的词汇。它们对C而言比较特殊,不能用它们作为标识符(如,变量名)。许多关键字 用于指定不同的类型,如int。还有一些关键字(如,if)用于控制程序中语句的执行顺序。在表 2.2 中 所列的C语言关键字中,粗体表示的是C90 标准新增的关键字,斜体表示的C99 标准新增的关键字,粗斜 体表示的是C11 标准新增的关键字。


C程序由一个或多个C 函数组成。每个C程序必须包含一个 main() 函数,这是C程序要调用的第1 个函数。简单的函数由函数头和后面的一对花括号组成,花括号中是由声明、语句组成的函数体。 在C语言中,大部分语句都以分号结尾。声明为变量创建变量名和标识该变量中储存的数据类型。变 量名是一种标识符。赋值表达式语句把值赋给变量,或者更一般地说,把值赋给存储空间。函数表达式语 句用于调用指定的已命名函数。调用函数执行完毕后,程序会返回到函数调用后面的语句继续执行。 printf()函数用于输出想要表达的内容和变量的值。 一门语言的语法是一套规则,用于管理语言中各有效语句组合在一起的方式。语句的语义是语句要表 达的意思。编译器可以检测出语法错误,但是程序里的语义错误只有在编译完之后才能从程序的行为中表 现出来。检查程序是否有语义错误要跟踪程序的状态,即程序每执行一步后所有变量的值。 最后,关键字是C语言的词汇。
更多推荐


所有评论(0)