C语言基础之C语言概述

C语言基础之C语言概述,第1张

C语言基础之C语言概述

Tips:

运算符:=
函数:main()、printf()
编写一个简单的C程序
创建整型变量,为其赋值并在屏幕上显示其值
换行字符
如何在程序中写注释,创建包含多个函数的程序,发现程序的错误
什么是关键字


Tips 2:

函数组成

命名方法

C程序是什么样子的?初见 C 程序会觉得 有些古怪,程序中有许多{、cp->tort和*ptr++这样的符号。然而,在学习C 的过程中,对这些符号和C语言特有的其他符号会越来越熟悉,甚至会喜欢上它们。如果熟悉与C相关的其他语言,会对C语言有似曾相识的感觉。本章,我们从演示一个简单的程序示例开始,解释该程序的功能。同时,强调 一些C语言的基本特性。
2.1 简单的C程序示例
我们来看一个简单的C程序,如程序清单2.1所示。该程序演示了用C语 言编程的一些基本特性。请先通读程序清单2.1,看看自己是否能明白该程 序的用途,再认真阅读后面的解释。
程序清单2.1 first.c程序
#include 
int main(void)         
{
int num;          
num = 1;          
printf("I am a simple "); 
printf("computer.n");
printf("My favorite number is %d because it is first.n",num);
return 0;
}
如果你认为该程序会在屏幕上打印一些内容,那就对了!光看程序也许 并不知道打印的具体内容,所以,运行该程序,并查看结果。首先,用你熟 悉的编辑器(或者编译器提供的编辑器)创建一个包含程序清单2.1 中所有 内容的文件。给该文件命名,并以.c作为扩展名,以满足当前系统对文件名 的要求。例如,可以使用first.c。现在,编译并运行该程序。如果一切运行正常,该程序的输出应该是:
I am a simple computer.
My favorite number is 1 because it is first.
总而言之,结果在意料之中,但是程序中的n 和%d 是什么?程序中有 几行代码看起来有点奇怪。接下来,我们逐行解释这个程序。
程序调整
程序的输出是否在屏幕上一闪而过?某些窗口环境会在单独的窗口运行 程序,然后在程序运行结束后自动关闭窗口。如果遇到这种情况,可以在程序中添加额外的代码,让窗口等待用户按下一个键后才关闭。一种方法是, 在程序的return语句前添加一行代码:
getchar();
这行代码会让程序等待击键,窗口会在用户按下一个键后才关闭。

我们会把程序清单2.1的程序分析两遍。第1遍(快速概要)概述程序中 每行代码的作用,帮助读者初步了解程序。第2遍(程序细节)详细分析代 码的具体含义,帮助读者深入理解程序。

 2.2.1 第1遍:快速概要
本节简述程序中的每行代码的作用。下一节详细讨论代码的含义。
#include   ←包含另一个文件
该行告诉编译器把stdio.h中的内容包含在当前程序中。stdio.h是C编译器 软件包的标准部分,它提供键盘输入和屏幕输出的支持。
int main(void)     ←函数名
C程序包含一个或多个函数,它们是C程序的基本模块。从上图可以看出:C语言基本组成是函数,函数里面有变量定义,块,表达式语句等组成。
 

2.2.2 第2遍:程序细节
浏览完程序清单2.1后,我们来仔细分析这个程序。再次强调,本节将 逐行分析程序中的代码,以每行代码为出发点,深入分析代码背后的细节, 为更全面地学习C语言编程的特性夯实基础。
1.#include指令和头文件
#include
这是程序的第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标准指定的头文件。
注意 为何不内置输入和输出
读者一定很好奇,为何不把输入和输出这些基本功能内置在语言中。原 因之一是,并非所有的程序都会用到I/O(输入/输出)包。轻装上阵表现了 C语言的哲学。正是这种经济使用资源的原则,使得C语言成为流行的嵌入 式编程语言(例如,编写控制汽车自动燃油系统或蓝光播放机芯片的代 码)。#include中的#符号表明,C预处理器在编译器接手之前处理这条指 令。本书后面章节中会介绍更多预处理器指令的示例,第16章将更详细地讨 论相关内容。
2.main()函数

int main(void);      //标准写法
程序清单2.1中的第2行表明该函数名为main。的确,main是一个极其普 通的名称,但是这是唯一的选择。C程序一定从main()函数开始执行(目前 不必考虑例外的情况)。除了main()函数,你可以任意命名其他函数,而且 main()函数必须是开始的函数。圆括号有什么功能?用于识别main()是一个函数。很快你将学到更多的函数。就目前而言,只需记住函数是C程序的基本模块。
int是main()函数的返回类型。这表明main()函数返回的值是整数。返回 到哪里?返回给 *** 作系统。我们将在第6章中再来探讨这个问题。
通常,函数名后面的圆括号中包含一些传入函数的信息。该例中没有传 递任何信息。因此,圆括号内是单词void(第11章将介绍把信息从main()函 数传回 *** 作系统的另一种形式)。
如果浏览旧式的C代码,会发现程序以如下形式开始:
main()
C90标准勉强接受这种形式,但是C99和C11标准不允许这样写。因此, 即使你使用的编译器允许,也不要这样写。
你还会看到下面这种形式:
void main()
一些编译器允许这样写,但是所有的标准都未认可这种写法。因此,编 译器不必接受这种形式,而且许多编译器都不能这样写。需要强调的是,只 要坚持使用标准形式,把程序从一个编译器移至另一个编译器时就不会出什 么问题。
3.注释


在程序中,被两个符号括起来的部分是程序的注释。写注释能让他 人(包括自己)更容易明白你所写的程序。C 语言注释的好处之一是,可将 注释放在任意的地方,甚至是与要解释的内容在同一行。较长的注释可单独 放一行或多行。在之间的内容都会被编译器忽略。
C99新增了另一种风格的注释,普遍用于C++和Java。这种新风格使用// 符号创建注释,仅限于单行。
// 这种注释只能写成一行。
int rigue; // 这种注释也可置于此。
因为一行末尾就标志着注释的结束,所以这种风格的注释只需在注释开 始处标明//符号即可。
这种新形式的注释是为了解决旧形式注释存在的潜在问题。
4.花括号、函数体和块
{
...
}

程序清单2.1中,花括号把main()函数括起来。一般而言,所有的C函数都使用花括号标记函数体的开始和结束。这是规定,不能省略。只有花括号 ({})能起这种作用,圆括号(())和方括号([])都不行。
花括号还可用于把函数中的多条语句合并为一个单元或块。如果读者熟 悉Pascal、ADA、Modula-2或者Algol,就会明白花括号在C语言中的作用类 似于这些语言中的begin和end。
5.声明
int num;
程序清单2.1中,这行代码叫作声明(declaration)。声明是C语言最重要的特性之一。在该例中,声明完成了两件事。其一,在函数中有一个名为 num的变量(variable)。其二,int表明num是一个整数(即,没有小数点或 小数部分的数)。int是一种数据类型。编译器使用这些信息为num变量在内存中分配存储空间。分号在C语言中是大部分语句和声明的一部分,不像在 Pascal中只是语句间的分隔符。
int是C语言的一个关键字(keyword),表示一种基本的C语言数据类 型。关键字是语言定义的单词,不能做其他用途。例如,不能用int作为函数 名和变量名。但是,这些关键字在该语言以外不起作用,所以把一只猫或一 个可爱的小孩叫int是可以的(尽管某些地方的当地习俗或法律可能不允 许)。
示例中的num是一个标识符(identifier),也就一个变量、函数或其他 实体的名称。因此,声明把特定标识符与计算机内存中的特定位置联系起 来,同时也确定了储存在某位置的信息类型或数据类型。
在C语言中,所有变量都必须先声明才能使用。这意味着必须列出程序 中用到的所有变量名及其类型。
以前的C语言,还要求把变量声明在块的顶部,其他语句不能在任何声
明的前面。也就是说,main()函数体如下所示:
int main() //旧规则
{
int doors;
int dogs;
doors = 5;
dogs = 3;
// 其他语句
}
C99和C11遵循C++的惯例,可以把声明放在块中的任何位置。尽管如此,首次使用变量之前一定要先声明它。因此,如果编译器支持这一新特性,可以这样编写上面的代码:
int main()      // 目前的C规则
{
// 一些语句
int doors;
doors = 5; // 第1次使用doors
// 其他语句
int dogs;
dogs = 3; // 第1次使用dogs

// 其他语句
}

数据类型
C 语言可以处理多种类型的数据,如整数、字符和浮点数。把变量声明 为整型或字符类型,计算机才能正确地储存、读取和解释数据。下一章将详 细介绍C语言中的各种数据类型。
命名
给变量命名时要使用有意义的变量名或标识符(如,程序中需要一个变 量数羊,该变量名应该是sheep_count而不是x3)。如果变量名无法清楚地表 达自身的用途,可在注释中进一步说明。这是一种良好的编程习惯和编程技 巧。
C99和C11允许使用更长的标识符名,但是编译器只识别前63个字符。 对于外部标识符(参阅第12章),只允许使用31个字符。〔以前C90只允许 6个字符,这是一个很大的进步。旧式编译器通常最多只允许使用8个字 符。〕实际上,你可以使用更长的字符,但是编译器会忽略超出的字符。也 就是说,如果有两个标识符名都有63个字符,只有一个字符不同,那么编译 器会识别这是两个不同的名称。如果两个标识符都是64个字符,只有最后一 个字符不同,那么编译器可能将其视为同一个名称,也可能不会。标准并未 定义在这种情况下会发生什么。
可以用小写字母、大写字母、数字和下划线(_)来命名。而且,名称的第1个字符必须是字符或下划线,不能是数字。表2.1给出了一些示例。

*** 作系统和C库经常使用以一个或两个下划线字符开始的标识符(如, _kcab),因此最好避免在自己的程序中使用这种名称。标准标签都以一个或两个下划线字符开始,如库标识符。这样的标识符都是保留的。这意味着,虽然使用它们没有语法错误,但是会导致名称冲突。
C语言的名称区分大小写,即把一个字母的大写和小写视为两个不同的字符。因此,stars和Stars、STARS都不同

8.return语句
return 0;
return语句[3]是程序清单2.1的最后一条语句。int main(void)中的int表明 main()函数应返回一个整数。C标准要求main()这样做。有返回值的C函数要 有return语句。该语句以return关键字开始,后面是待返回的值,并以分号结 尾。如果遗漏 main()函数中的 return 语句,程序在运行至最外面的右花括号 (})时会返回0。因此,可以省略main()函数末尾的return语句。但是,不要 在其他有返回值的函数中漏掉它。因此,强烈建议读者养成在 main()函数中 保留 return 语句的好习惯。在这种情况下,可将其看作是统一代码风格。但 对于某些 *** 作系统(包括Linux和UNIX),return语句有实际的用途。

2.3 简单程序的结构
在看过一个具体的程序示例后,我们来了解一下C程序的基本结构。程序由一个或多个函数组成,必须有 main()函数。函数由函数头和函数体组成。函数头包括函数名、传入该函数的信息类型和函数的返回类型。通过函数名后的圆括号可识别出函数,圆括号里可能为空,可能有参数。函数体被花括号括起来,由一系列语句、声明组成,如图2.4所示。本章的程序示例 中有一条声明,声明了程序使用的变量名和类型。然后是一条赋值表达式语句,变量被赋给一个值。接下来是3条printf()语句[4],调用printf()函数3次。 最后,main()以return语句结束

 2.4 提高程序可读性的技巧
编写可读性高的程序是良好的编程习惯。可读性高的程序更容易理解, 以后也更容易修改和更正。提高程序的可读性还有助于你理清编程思路。
前面介绍过两种提高程序可读性的技巧:选择有意义的函数名和写注释。注意,使用这两种技巧时应相得益彰,避免重复啰嗦。如果变量名是 width,就不必写注释说明该变量表示宽度,但是如果变量名是 video_routine_4,就要解释一下该变量名的含义。
提高程序可读性的第3个技巧是:在函数中用空行分隔概念上的多个部 分。例如,程序清单2.1中用空行把声明部分和程序的其他部分区分开来。C 语言并未规定一定要使用空行,但是多使用空行能提高程序的可读性。
提高程序可读性的第4个技巧是:每条语句各占一行。同样,这也不是 C语言的要求。C语言的格式比较自由,可以把多条语句放在一行,也可以 每条语句独占一行

 2.6 多个函数
到目前为止,介绍的几个程序都只使用了printf()函数。程序清单2.3演 示了除main()以外,如何把自己的函数加入程序中。
程序清单2.3 two_func.c程序
/
#include 
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");
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();
早期的C代码中的函数声明就类似上面这样,不是现在的函数原型。 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()的函数原型。

本节内容:函数的声明,调用,定义,以及C语言程序的排布位置(main函数在最前)

2.7 调试程序
现在,你可以编写一个简单的 C 程序,但是可能会犯一些简单的错误。程序的错误通常叫做 bug,找出并修正错误的过程叫做调试(debug)

如何发现程序的语法错误?首先,在编译之前,浏览源代码看是否能发现一些明显的错误。接下来,查看编译器是否发现错误,检查程序的语法错 误是它的工作之一。在编译程序时,编译器发现错误会报告错误信息,指出 每一处错误的性质和具体位置。
尽管如此,编译器也有出错的时候。也许某处隐藏的语法错误会导致编译器误判。例如,由于nogood.c程序未正确声明n2和n3,会导致编译器在使 用这些变量时发现更多问题。实际上,有时不用把编译器报告的所有错误逐 一修正,仅修正第 1 条或前几处错误后,错误信息就会少很多。继续这样做,直到编译器不再报错。编译器另一个常见的毛病是,报错的位置比真正 的错误位置滞后一行。例如,编译器在编译下一行时才会发现上一行缺少分号。因此,如果编译器报错某行缺少分号,请检查上一行。
2.7.3 程序状态
通过逐步跟踪程序的执行步骤,并记录每个变量,便可监视程序的状态。程序状态(program state)是在程序的执行过程中,某给定点上所有变量值的集合。它是计算机当前状态的一个快照。
我们刚刚讨论了一种跟踪程序状态的方法:自己模拟计算机逐步执行程序。但是,如果程序中有10000次循环,这种方法恐怕行不通。不过,你可以跟踪一小部分循环,看看程序是否按照预期的方式执行。另外,还要考虑 一种情况:你很可能按照自己所想去执行程序,而不是根据实际写出来的代码去执行。因此,要尽量忠实代码来模拟。
定位语义错误的另一种方法是:在程序中的关键点插入额外的 printf() 语句,以监视制定变量值的变化。通过查看值的变化可以了解程序的执行情 况。对程序的执行满意后,便可删除额外的 printf()语句,然后重新编译。
检测程序状态的第3种方法是使用调试器。调试器(debugger)是一种 程序,让你一步一步运行另一个程序,并检查该程序变量的值。调试器有不同的使用难度和复杂度。较高级的调试器会显示正在执行的源代码行号。这 在检查有多条执行路径的程序时很方便,因为很容易知道正在执行哪条路 径。如果你的编译器自带调试器,现在可以花点时间学会怎么使用它。

2.8 关键字和保留标识符
关键字是C语言的词汇。它们对C而言比较特殊,不能用它们作为标识 符(如,变量名)。许多关键字用于指定不同的类型,如 int。还有一些关键字(如,if)用于控制程序中语句的执行顺序。在表 2.2 中所列的C语言关 键字中,粗体表示的是C90标准新增的关键字,斜体表示的C99标准新增的 关键字,粗斜体表示的是C11标准新增的关键字

 如果使用关键字不当(如,用关键字作为变量名),编译器会将其视为语法错误。还有一些保留标识符(reserved identifier),C语言已经指定了它们的用途或保留它们的使用权,如果你使用这些标识符来表示其他意思会导致一些问题。因此,尽管它们也是有效的名称,不会引起语法错误,也不能随便使用。保留标识符包括那些以下划线字符开头的标识符和标准库函数名,如printf()

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

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5714761.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-17
下一篇 2022-12-17

发表评论

登录后才能评论

评论列表(0条)

保存