C语言入门教程,C语言学习教程(第二部分:C语言初探)二

C语言入门教程,C语言学习教程(第二部分:C语言初探)二_第1张图片

十、C语言的三套标准:C89、C99和C11

我们今天使用的 Windows、Linux、Mac OS 等操作系统都是由一种叫做 Unix 的系统演化而来。Unix 作为80年代主流的操作系统,是整个软件工业的基础,是现代操作系统的开山鼻祖,C语言就是为 Unix 而生的。

Unix 和C语言的开发者是同一人,名字叫丹尼斯·里奇(Dennis MacAlistair Ritchie)

C语言入门教程,C语言学习教程(第二部分:C语言初探)二_第2张图片

​C语言和 Unix 之父——丹尼斯·里奇

2011年10月12日(北京时间为10月13日),丹尼斯·里奇去世,享年70岁。

1、C语言的诞生

1967年,26岁的丹尼斯·里奇进入贝尔实验室开发 Unix,并于 1969 年圣诞节前推出第一个试运行版本。这个时候的 Unix 是用汇编语言写的,移植性非常差,要想让 Unix 运行在不同型号的机器上,就得针对每个型号的机器重写一遍操作系统,这显然是一个不可能完成的任务。

为了提高通用性和开发效率,丹尼斯·里奇决定发明一种新的编程语言——C语言。紧接着,丹尼斯·里奇就用C语言改写了 Unix 上的C语言编译器,他的同事汤姆森则使用C语言重写了 Unix,使它成为一种通用性强、移植简单的操作系统,从此开创了计算机编程史上的新篇章,C语言也成为了操作系统专用语言。

2、C89 标准

到了80年代,C语言越来越流行,广泛被业界使用,从大型主机到小型微机,各个厂商群雄并起,推出了多款C语言的编译器。这些编译器根据行业和厂商自己的需求,进行了各种扩展,C语言进入了春秋战国时代,逐渐演变成一个松散杂乱的大家族。

为统一C语言版本,1983 年美国国家标准局(American National Standards Institute,简称 ANSI)成立了一个委员会,专门来制定C语言标准。1989 年C语言标准被批准,被称为 ANSI X3.159-1989 "Programming Language C"。这个版本的C语言标准通常被称为 ANSI C。又由于这个版本是 89 年完成制定的,因此也被称为 C89

后来 ANSI 把这个标准提交到 ISO(国际化标准组织),1990 年被 ISO 采纳为国际标准,称为 ISO C。又因为这个版本是1990年发布的,因此也被称为 C90

ANSI C(C89)与 ISO C(C90)内容基本相同,主要是格式组织不一样。

因为 ANSI 与 ISO 的C标准内容基本相同,所以对于C标准,可以称为 ANSI C,也可以说是 ISO C,或者 ANSI / ISO C。以后大家看到 ANSI C、ISO C、C89、C90,要知道这些标准的内容都是一样的。

目前常用的编译器,例如微软编译器、GCC、LLVM/Clang 等,都能很好地支持 ANSI C 的内容。

2、C99 标准

在 ANSI C 标准确立之后,C语言的规范在很长一段时间内都没有大的变动。1995 年C程序设计语言工作组对C语言进行了一些修改,增加了新的关键字,编写了新的库,取消了原有的限制,并于 1999 年形成新的标准——ISO/IEC 9899:1999 标准,通常被成为 C99

但是这个时候的C语言编译器基本已经成熟,各个组织对 C99 的支持所表现出来的兴趣不同。当 GCC 和其它一些商业编译器支持 C99 的大部分特性的時候,微软和 Borland 却似乎对此不感兴趣,或者说没有足够的资源和动力来改进编译器,最终导致不同的编译器在部分语法上存在差异。

例如,ANSI C 规定,局部变量要在函数开头定义,而 C99 取消了这个限制,变量可以在任意位置定义,我们将在《C语言变量的定义位置以及初始值》一节中详细介绍。

3、C11 标准

C11 标准由国际标准化组织(ISO)和国际电工委员会(IEC) 旗下的C语言标准委员会于 2011 年底正式发布,支持此标准的主流C语言编译器有 GCC、LLVM/Clang、Intel C++ Compile 等。

C11 标准主要增加了以下内容:

  • 增加了安全函数,例如 gets_s()、fopen_s() 等;
  • 增加了  头文件以支持多线程;
  • 增加了  头文件以支持 Unicode 字符集;
  • 以及其它一些细节。

2018 年,ISO/IEC 又发布了 C11 标准的修正版,称为 C17 或者 C18 标准。和 C11 标准相比,C17 并没有添加新的功能和语法特性,仅仅修正了 C11 标准中已知的一些缺陷。

截至到 2022 年 7 月份,新的 C2x 标准尚未发布,最新的 C 语言标准仍是 C17。

4、总结

现有的教程(包括书籍、视频、大学课程等)大都是针对 C89 编写的,这是C语言的核心,后来的 C99、C11 新增的特性并不多,只是在“打补丁”。本教程虽然基于 C99 标准,但是绝大部分内容还是 C89 的,我会在 C89 和 C99 有差异的语法上给出重点说明。


十一、C语言为什么有那么多编译器?

通过上节《C语言的三套标准:C89、C99和C11》的介绍可以发现,C语言并没有一个官方机构,也不属于哪个公司,它只有一个制定标准的委员会,任何其他组织或者个人都可以开发C语言的编译器,而这个编译器要遵守哪个C语言标准,是 100% 遵守还是部分遵守,并没有强制性的措施,也没有任何约束。

换句话说,各个厂商可以为了自己的利益、根据自己的喜好来开发编译器。

这就导致了一个棘手的问题,有的编译器遵守较新的C语言标准,有的编译器只能遵守较老的C语言标准,有的编译器还进行了很多扩展。比如:

  • GCC、LLVM/Clang 更新非常及时,能够支持最新的 C11 标准(前提是你得使用最新版的编译器)。
  • 微软编译器更新比较缓慢,迟迟不能支持新标准。 例如 VC 6.0、VS2010 都在使用 C89 标准,VS2015 部分支持 C99 标准,直到 VS2019 才部分支持 C11 和 C17 标准。微软官方给出的答复是,最新的标准已经在 C++ 中支持了,C语言就没必要再重复了。

初学者经常会遇到这种情况,有些代码在微软编译器下能够正常运行,拿到 GCC 下就不行了,一堆报错信息;或者反过来,在 GCC 上能运行的代码在微软编译器下不能运行。这是因为不同的编译器支持不同的标准,并且每个编译器都进行了自己的扩展,假如你使用了微软编译器私有的扩展函数,那么拿到 GCC 下肯定是不支持的。


十二、程序安装是怎么回事?

我们知道,大部分软件都需要先安装才能使用,例如 QQ、360、迅雷等,要先从网上下载一个安装包,然后安装到计算机的C盘或者D盘等。大部分程序还会在开始菜单或者桌面上生成一个快捷方式,用户只要点击快捷方式,就可以启动软件。

那么,一个程序为什么要安装呢?下载后直接使用不可以吗?下面我们就来分析一下。

不同的操作系统,安装软件的方法虽然不一样,但基本原理是相同的,主要的思想就是将程序的二进制可执行文件拷贝到某个目录,设置一些路径。如果程序运行时需要一些库,将这些库拷贝到系统目录即可。

程序的安装基本上要经过下面四个步骤:

1) 将程序的可执行文件从安装包所在的位置,拷贝到要安装的目录。

安装程序的时候,程序会给用户指定一个默认的安装目录,如果用户需要,也可以自定义安装,改变安装目录。一般所谓的“绿色软件”到此就安装结束了,可以使用了。

2) 如果有必要,可以向系统目录拷贝一些动态链接库(DLL)。(可选操作)

有的程序,比如大型游戏,可能需要很多动态链接库(DLL)的支持,这时候程序可能会将这些 DLL 拷贝到系统库的默认目录,Win7 下一般拷贝到C:\\Windows\System32\读者不妨打开该目录,会看到很多 DLL 文件)。

有些程序用到的 DLL 文件不是系统必需的,只能由程序自己使用,这样放在系统目录里就不太合适,安装的软件多了,就会造成系统臃肿,所以这些 DLL 会被拷贝到程序的安装目录。

3) 向系统注册表中写入相应的设置项,注册程序或者库的安装信息。(可选操作)

安装前,用户可能会对软件做一些设置,安装时,这些设置就会被写入注册表。另外,当安装程序将 DLL 文件拷贝到系统目录时,一些 DLL 还需要向系统注册,告诉系统我在这里,不然使用的时候可能会找不到。

4) 在开始菜单或者桌面上位程序创建快捷方式。(可选操作)

创建快捷方式主要是为了用户使用方便,有了快捷方式,就不用再到安装目录去启动程序了。

由此可见,程序在安装前后并没有什么区别,只不过是进行了一些设置,有的设置是程序运行所必须的,有的是为了让用户更加方便。


十三、制作安装包,让用户安装程序

经过多年的发展,Windows 安装包的制作技术已经非常成熟,有不少现成的工具,无需我们自己编写代码,例如 Inno Setup、NSIS、Advanced Installer、Setup Factory、Smart Install Maker、Nullsoft、InstallShield,Advanced Installer 等。

软件安装的过程大部分是文件拷贝的过程,如果不需要写入注册表,不需要向不同的目录拷贝 DLL,那么使用 WinRAR 也可以制作简单的安装包,大家可以自行谷歌或百度。这里我们教大家使用 VS2022 制作安装包。

C语言入门教程,C语言学习教程(第二部分:C语言初探)二_第3张图片

图 1 制作安装包的 C 语言项目

以图 1 中的 C 语言项目为例,编译后会生成一个名为“Demo.exe”的可执行文件,在 Demo 项目的本地文件夹中可以找到它,利用 VS2022 将 Demo.exe 制作成安装包需要经历以下几个步骤。

1、安装Installer Projects

Installer Projects 是 VS2022 自带的一款制作安装包的插件,借助它,在 VS 中编写的程序可以打包成标准的 Windows 安装包。

安装 Installer Projects 的过程很简单,在 VS2022 菜单栏中依次选择“扩展 -> 管理扩展”,会弹出如下的窗口:

C语言入门教程,C语言学习教程(第二部分:C语言初探)二_第4张图片

图 2 安装 Installer Projects 组件

搜索框中手动输入“Visual Studio Installer Projects”找到 Installer Projects 组件,点击“下载”。整个安装的过程非常简单,这里不再给出具体图示。

安装完成后,重启 VS2022,就可以使用 Installer Projects 组件了。

2、新建制作安装包的项目

在 Demo 项目所在的解决方案中,再新建一个制作安装包的项目(也可以单独创建一个制作安装包的项目):

C语言入门教程,C语言学习教程(第二部分:C语言初探)二_第5张图片

图 3 新建制作安装包的项目

在弹出的如下窗口中,选择创建“Setup Project”项目:

C语言入门教程,C语言学习教程(第二部分:C语言初探)二_第6张图片

图 4 创建 Setup Project 项目

注意,如果找不到 Setup Project 项目,表明你的 VS2022 尚未安装 Installer Projects,返回第 1 步安装成功后再继续往下进行。

在弹出的如下窗口中,可以自定义项目的名称和存储位置:

C语言入门教程,C语言学习教程(第二部分:C语言初探)二_第7张图片

图 5 自定义项目名称和存储位置

创建完成后,当前解决方案中就包含了两个项目,一个是 Demo 项目,另一个是 DemoSetup 项目:

C语言入门教程,C语言学习教程(第二部分:C语言初探)二_第8张图片

​图 6 一个解决方案中包含两个项目

3、制作安装包

鼠标右击图 6 中的 DemoSetup 项目名,依次选择“View -> 文件系统”,可以看到 3 个文件夹:

  • Application Folder(应用程序文件夹):放置制作安装包所需的所有文件,包括可执行文件、库文件、icon 图标等;
  • User's Desktop(用户的桌面):指定用户安装应用程序完成后,桌面上需要放置的内容,通常是可执行程序的快捷方式;
  • User's Programs Menu(用户的程序菜单):指定用户安装应用程序完成后,开始菜单中需要显示的内容,比如可执行程序和卸载程序的快捷方式。

(1) 应用程序文件夹中添加文件

在应用程序文件夹处单击鼠标右键选择“添加(Add) -> 文件夹(Floder)”,如下图所示:

C语言入门教程,C语言学习教程(第二部分:C语言初探)二_第9张图片

图 7 应用程序文件夹中添加文件夹

我们不妨将文件夹命名为 Demo。这个文件夹就是程序安装后所在安装路径下生成的、包含程序相关组件的文件夹。例如,用户选择将程序安装到 D:\Program Files\ 目录,那么安装时会先在该目录创建一个名称为 Demo 的新文件夹,再将程序的所有组件拷贝到 Demo 中,最终程序的所有文件是在 D:\Program Files\Demo\ 目录下。

接下来,向 Demo 文件夹中添加程序要用到的所有文件,如下图所示:

C语言入门教程,C语言学习教程(第二部分:C语言初探)二_第10张图片

图 8 应用程序文件夹中添加文件

添加好以后如下图所示:

C语言入门教程,C语言学习教程(第二部分:C语言初探)二_第11张图片

图 9 添加好的文件

Demo.exe 是我们编译好的可执行文件,demo.ico 和 uninstall.ico 是图标,用来创建快捷方式。程序图标必须是 .ico 格式,可以通过 jpg、png 等常见图片格式在线转换。文章最后会给出两个图标的下载地址。

制作安装包之前,可以将程序使用到的所有文件都拷贝到一个目录下,这样就可以一次性添加到 Demo。

增加卸载功能

如果想为安装包增加卸载功能的话,还需要将C:\Windows\System32\msiexec.exe也添加到 CDemo 中。

(2)桌面和开发菜单中添加快捷方式

快捷方式存在于两个地方,分别是桌面和开始菜单,用户的程序菜单用来存放开始菜单中的快捷方式,用户的桌面用来存放桌面上的快捷方式。

在 "Demo.exe" 上单击鼠标右键选择创建 Demo.exe 的快捷方式,如下图所示:

C语言入门教程,C语言学习教程(第二部分:C语言初探)二_第12张图片

图 10 添加 Demo.exe 的快捷方式

鼠标右击新生成的快捷方式(Shortcut to Demo.exe),选择“属性窗口”,下图所示:

C语言入门教程,C语言学习教程(第二部分:C语言初探)二_第13张图片

图 11 快捷方式的属性

Name 表示快捷方式的名称,一般是程序名,这里重置为 Demo;Description 表示对快捷方式的说明,也就是鼠标悬浮时显示的文本;Target 表示快捷方式指向哪个可执行程序;Icon 表示快捷方式的图标,将其设置为 demo.ico 。

按照同样的方式为 msiexec.exe 也生成快捷方式,并将 Name 设置为“卸载Demo”,将 Icon 设置为“uninstall.ico”。

在“用户的程序菜单”下新建文件夹 Demo,将两个快捷方式移动到此文件夹下。然后再为 demo.exe 创建一个快捷方式,并移动到“用户的桌面”下。

这样,程序安装后在桌面和开始菜单中都有快捷方式,都可以启动了。

(3)实现卸载功能(可选)

上面我们虽然添加了系统自带的卸载程序,并为卸载程序创建了快捷方式,但目前依然无法实现卸载功能,因为还不知道要卸载哪个程序。

在图 11 属性面板的基础上,鼠标点击项目名 DemoSetup,可以看到和此项目有关的属性,如下图所示:

C语言入门教程,C语言学习教程(第二部分:C语言初探)二_第14张图片

​图 12 项目属性面板

ProductCode 是产品代码,即产品 ID,我们需要将它告诉卸载程序。每个程序的 ID 都不同,有了它,卸载程序才知道卸载哪一个软件。本例中,程序 ID 为 {FF9566C2-47D6-4B1F-95D4-67C4EDD2F7D6}。

在卸载程序 msiexec.exe 快捷方式的属性面板中,将 Arguments 的值设置为/x{FF9566C2-47D6-4B1F-95D4-67C4EDD2F7D6},如下图所示:

C语言入门教程,C语言学习教程(第二部分:C语言初探)二_第15张图片

​图 13 实现卸载功能

这样,卸载程序就知道卸载哪个软件了。

(4)选择系统必备

在项目名称 DemoSetup 上点击鼠标右键,选择“属性”,弹出如下的对话框:

C语言入门教程,C语言学习教程(第二部分:C语言初探)二_第16张图片

图 14 设置系统必备

点击“Prerequisites...”(系统必备),弹出如下窗口:

C语言入门教程,C语言学习教程(第二部分:C语言初探)二_第17张图片

图 15 自选系统必备的组件

可以在这里选择程序需要的系统组件。我们的程序不需要任何组件,所以将【创建用于安装系统必备组件的安装程序】前的对勾取消,然后点击“确定”按钮,就设置完成了。

至此,我们的安装包就编辑完成了。

(5) 生成安装包

鼠标右击 DemoSetup 项目名,选择“生成”或者“重新生成”:

C语言入门教程,C语言学习教程(第二部分:C语言初探)二_第18张图片

图 16 生成安装包

生成项目后,可以在 Debug 目录下看到 CDemoSetup.msi 文件,这就是我们制作好的安装包,双击运行,就可以安装我们的程序了。

安装完成后,就可以在开始菜单和桌面上看到快捷方式了,如下图所示:

C语言入门教程,C语言学习教程(第二部分:C语言初探)二_第19张图片

​图 17 安装好的应用程序

点击 Demo,可以看到程序的运行结果;点击“卸载 Demo”,可以卸载 Demo 应用程序。

程序图标下载地址:http://pan.baidu.com/s/1pK0fwIR  提取密码:iux9


十四、C语言程序的错误和警告

一段C语言代码,在编译、链接和运行的各个阶段都可能会出现问题。编译器只能检查编译和链接阶段出现的问题,而可执行程序已经脱离了编译器,运行阶段出现问题编译器是无能为力的。

如果我们编写的代码正确,运行时会提示没有错误(Error)和警告(Warning),如下图所示:

C语言入门教程,C语言学习教程(第二部分:C语言初探)二_第20张图片

图1:Dev C++ 的提示

C语言入门教程,C语言学习教程(第二部分:C语言初探)二_第21张图片

​图2:VC 6.0 的提示

C语言入门教程,C语言学习教程(第二部分:C语言初探)二_第22张图片

​图3:C-Free 5.0 的提示

对于 VS、GCC、Xcode 等,如果代码没有错误,它们只会显示“生成成功”,不会显示“0个错误,0个警告”,只有代码真的出错了,它们才会显示具体的错误信息。

错误(Error)表示程序不正确,不能正常编译、链接或运行,必须要纠正。

警告(Warning)表示可能会发生错误(实际上未发生)或者代码不规范,但是程序能够正常运行,有的警告可以忽略,有的要引起注意。

错误和警告可能发生在编译、链接、运行的任何时候。

例如,puts("C语言中文网")最后忘记写分号;,就会出现错误,如下图所示:

C语言入门教程,C语言学习教程(第二部分:C语言初探)二_第23张图片

图4:VS2015 的错误提示

C语言入门教程,C语言学习教程(第二部分:C语言初探)二_第24张图片

​图5:Dev C++ 的错误提示

C语言入门教程,C语言学习教程(第二部分:C语言初探)二_第25张图片

图6:VC 6.0 的错误提示

C语言入门教程,C语言学习教程(第二部分:C语言初探)二_第26张图片

​图7:C-Free 5.0 的错误提示

可以看出,C-Free 的错误提示信息比较少,不方便程序员纠错。VC 和 VS 的错误信息类似,只是中英文的差别。

下图分析了 VC 6.0 的错误信息:

C语言入门教程,C语言学习教程(第二部分:C语言初探)二_第27张图片

图8:错误信息说明

翻译:源文件 E:\cDemo\hello.c 第5行发生了语法错误,错误代码是 C2143,原因是 'return' 前面丢失了 ';'。

我敢保证,你写的代码肯定会发生错误,一定要有分析错误的能力,这是一个合格的程序员必备的技能。


十五、分析第一个C语言程序

前面我们给出了一段最简单的C语言代码,并演示了如何在不同的平台下进行编译,这节我们来分析一下这段代码,让读者有个整体的认识。代码如下:

#include

int main()

{

         puts("C语言中文网");

         return 0;

}

1、函数的概念

先来看第 4 行代码,这行代码会在显示器上输出“C语言中文网”。前面我们已经讲过,puts 后面要带( ),字符串也要放在( )中。

在C语言中,有的语句使用时不能带括号,有的语句必须带括号。带括号的称为函数(Function)

C语言提供了很多功能,例如输入输出、获得日期时间、文件操作等,我们只需要一句简单的代码就能够使用。但是这些功能的底层都比较复杂,通常是软件和硬件的结合,还要要考虑很多细节和边界,如果将这些功能都交给程序员去完成,那将极大增加程序员的学习成本,降低编程效率。

好在C语言的开发者们为我们做了一件好事,他们已经编写了大量代码,将常见的基本功能都完成了,我们可以直接拿来使用。但是现在问题来了,那么多代码,如何从中找到自己需要的呢?一股脑将所有代码都拿来显然是非常不明智的。

这些代码,早已被分门别类地放在了不同的文件中,并且每一段代码都有唯一的名字。使用代码时,只要在对应的名字后面加上( )就可以。这样的一段代码能够独立地完成某个功能,一次编写完成后可以重复使用,被称为函数(Function)。读者可以认为,函数就是一段可以重复使用的代码。

函数的一个明显特征就是使用时必须带括号( ),必要的话,括号中还可以包含待处理的数据。例如puts("C语言中文网")就使用了一段具有输出功能的代码,这段代码的名字是 puts,"C语言中文网" 是要交给这段代码处理的数据。使用函数在编程中有专业的称呼,叫做函数调用(Function Call)

如果函数需要处理多个数据,那么它们之间使用逗号,分隔,例如:

pow(10, 2);

该函数用来求10的2次方。

需要注意的是,C语言中的函数和数学中的函数不是同一个概念,不要拿两者对比。函数的英文名称是 Function,它还有“功能”的意思。大陆将 Function 翻译为“函数”,而台湾地区翻译为“函式”,读者要注意区分。

2、自定义函数和main函数

C语言自带的函数称为库函数(Library Function)库(Library)是编程中的一个基本概念,可以简单地认为它是一些列函数的集合,在磁盘上往往是一个文件夹。C语言自带的库称为标准库(Standard Library),其他公司或个人开发的库称为第三方库(Third-Party Library)

关于库的概念,我们已在《不要这样学习C语言,这是一个坑!》中进行了详细介绍。

除了库函数,我们还可以编写自己的函数,拓展程序的功能。自己编写的函数称为自定义函数。自定义函数和库函数在编写和使用方式上完全相同,只是由不同的机构来编写。

示例中第2~6行代码就是我们自己编写的一个函数。main 是函数的名字,( ) 表明这是函数定义,{ } 之间的代码是函数要实现的功能。

函数可以接收待处理的数据,同样可以将处理结果告诉我们;使用return可以告知处理结果。示例中第5行代码表明,main 函数的处理结果是整数 0。return 可以翻译为“返回”,所以函数的处理结果被称为返回值(Return Value)

第2行代码中,int 是 integer 的简写,意为“整数”。它告诉我们,函数的返回值是整数。

需要注意的是,示例中的自定义函数必须命名为 main。C语言规定,一个程序必须有且只有一个 main 函数。main 被称为主函数,是程序的入口函数,程序运行时从 main 函数开始,直到 main 函数结束(遇到 return 或者执行到函数末尾时,函数才结束)。

也就是说,没有 main 函数程序将不知道从哪里开始执行,运行时会报错。

综上所述:第2~6行代码定义了主函数 main,它的返回值是整数 0,程序将从这里开始执行。main 函数的返回值在程序运行结束时由系统接收。

关于自定义函数的更多内容,我们将在《C语言函数详解(包括声明、定义、使用等)》一章中详细讲解,这里不再展开讨论。

有的教材中将 main 函数写作:

void main()

{

         // Some Code...

}

这在 VC6.0 下能够通过编译,但在 C-Free、GCC中却会报错,因为这不是标准的 main 函数的写法,大家不要被误导,最好按照示例中的格式来写。

3、头文件的概念

还有最后一个问题,示例中第1行的#include 是什么意思呢?

C语言开发者们编写了很多常用函数,并分门别类的放在了不同的文件,这些文件就称为头文件(header file)。每个头文件中都包含了若干个功能类似的函数,调用某个函数时,要引入对应的头文件,否则编译器找不到函数。

实际上,头文件往往只包含函数的说明,也就是告诉我们函数怎么用,而函数本身保存在其他文件中,在链接时才会找到。对于初学者,可以暂时理解为头文件中包含了若干函数。

引入头文件使用#include命令,并将文件名放在< >中,#include 和 < > 之间可以有空格,也可以没有。

头文件以.h为后缀,而C语言代码文件以.c为后缀,它们都是文本文件,没有本质上的区别,#include 命令的作用也仅仅是将头文件中的文本复制到当前文件,然后和当前文件一起编译。你可以尝试将头文件中的内容复制到当前文件,那样也可以不引入头文件。

.h中代码的语法规则和.c中是一样的,你也可以#include ,这是完全正确的。不过实际开发中没有人会这样做,这样看起来非常不专业,也不规范。

较早的C语言标准库包含了15个头文件,stdio.h 和 stdlib.h 是最常用的两个:

  • stdio 是 standard input output 的缩写,stdio.h 被称为“标准输入输出文件”,包含的函数大都和输入输出有关,puts() 就是其中之一。
  • stdlib 是 standard library 的缩写,stdlib.h 被称为“标准库文件”,包含的函数比较杂乱,多是一些通用工具型函数,system() 就是其中之一。

4、最后的总结

初学编程,有很多基本概念需要了解,本节就涉及到很多,建议大家把上面的内容多读几遍,必将有所收获。

本节开头的示例是一个C语言程序的基本结构,我们不妨整理一下思路,从整体上再分析一遍:
1) 第1行引入头文件 stdio.h,这是编程中最常用的一个头文件。头文件不是必须要引入的,我们用到了 puts 函数,所以才引入 stdio.h。例如下面的代码完全正确:

int main()

{

         return 0;

}

我们没有调用任何函数,所以不必引入头文件。

2) 第2行开始定义主函数 main。main 是程序的入口函数,一个C程序必须有 main 函数,而且只能有一个。

3) 第4行调用 puts 函数向显示器输出字符串。

4) 第5行是 main 函数的返回值。程序运行正确一般返回 0。


十六、C语言代码中的空白符

空格、制表符、换行符等统称为空白符(space character),它们只用来占位,并没有实际的内容,也显示不出具体的字符。

制表符分为水平制表符和垂直制表符,它们的 ASCII 编码值分别是 9 和 11。

  • 垂直制表符在现代计算机中基本不再使用了,也没法在键盘上直接输入,它已经被换行符取代了。
  • 水平制表符相当于四个空格,对于大部分编辑器,按下 Tab 键默认就是输入一个水平制表符;如果你进行了个性化设置,按下 Tab 键也可能会输入四个或者两个空格。

对于编译器,有的空白符会被忽略,有的却不能。请看下面几种 puts 的写法:

#include

int main()

{

         puts("C语言");

         puts("中文网");

         puts

        ("C语言中文网");

        puts

         (

         "C语言中文网"

         )

        ;        

        puts          ("C语言中文网");

         puts         (          "C语言中文网"          )         ;

         return 0;

}

运行结果:

C语言入门教程,C语言学习教程(第二部分:C语言初探)二_第28张图片

看到输出结果,说明代码没有错误,以上几种 puts 的用法是正确的。puts()之间、" "()之间可以有任意的空白符,它们会被编译器忽略,编译器不认为它们是代码的一部分,它们的存在只是在编辑器中呈现一定的格式,让程序员阅读方便。

需要注意的是,由" "包围起来的字符串中的空白符不会被忽略,它们会被原样输出到控制台上;并且字符串中间不能换行,否则会产生编译错误。请看下面的代码:

#include

int main()

{

         puts("C语   言   中文网");

         puts("C语言

         中文网");

         return 0;

}

第 5~6 行代码是错误的,字符串必须在一行内结束,不能换行。把这两行代码删除,运行结果为:

C语言入门教程,C语言学习教程(第二部分:C语言初探)二_第29张图片



程序员要善于利用空白符:缩进(制表符)和换行可以让代码结构更加清晰,空格可以让代码看起来不那么拥挤。专业的程序员同样追求专业的代码格式,大家在以后的学习中可以慢慢体会。


十七、彩色版的C语言,让文字更漂亮

对于初学者来说,本节涉及到的代码比较复杂,名字也不容易记住,大家只需要把代码复制到编译器,看一下运行效果就可以。本节重在演示C语言能做什么,而不是教授大家知识点(这些知识点也不是C语言的重点),所以,不理解的就放过吧,不会影响后面的学习。

C语言不总是“黑底白字”,它也可以是彩色的,可以调用Windows.h文件下的SetConsoleTextAttribute函数改变文字和背景颜色。

调用形式为:

SetConsoleTextAttribute( HANDLE hConsoleOutput, WORD wAttributes );

hConsoleOutput表示控制台缓冲区句柄,可以通过GetStdHandle(STD_OUTPUT_HANDLE)来获得;wAttributes表示文字颜色和背景颜色。

WORDwindows.h中定义,等同于unsigned short,使用低4位表示文字(前景)颜色,高4位表示文字背景颜色,所以它的取值为xx。x为一位16进制数,即0~F都可以使用,可以随意组合。

0~F 分别代表的颜色如下:

0 = 黑色    8 = 灰色    1 = 淡蓝      9 = 蓝色
2 = 淡绿    A = 绿色    3 = 湖蓝      B = 淡浅绿  
C = 红色    4 = 淡红    5 = 紫色      D = 淡紫  
6 = 黄色    E = 淡黄    7 = 白色      F = 亮白

例如,将背景设置为淡绿色,文字设置为红色

#include

#include

int main(){

        HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);         SetConsoleTextAttribute(hConsole, 0x2C );

        puts("C语言中文网");

        return 0;

}

运行结果:

C语言入门教程,C语言学习教程(第二部分:C语言初探)二_第30张图片

如果只希望设置文字颜色,背景保持黑色,那么也可以只给出一位16进制数,例如:

SetConsoleTextAttribute(hConsole, 0xC ); //将文字颜色设置为红色 SetConsoleTextAttribute(hConsole, 0xF ); //将文字颜色设置为白色

再来看一个例子:

#include

#include

int main(){

         HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);

         SetConsoleTextAttribute(hConsole, 0xC );

         puts("红色文字");

         SetConsoleTextAttribute(hConsole, 0xF );

         puts("白色文字");

         SetConsoleTextAttribute(hConsole, 2 );

         puts("淡绿色文字");

         return 0;

}

运行结果:

C语言入门教程,C语言学习教程(第二部分:C语言初探)二_第31张图片


十八、一个真正带界面的C语言程序

对于初学者来说,本节涉及到的代码比较复杂,名字也不容易记住,大家只需要把代码复制到编译器,看一下运行效果就可以。本节重在演示C语言能做什么,而不是教授大家知识点(这些知识点也不是C语言的重点),所以,不理解的就放过吧,不会影响后面的学习。

C语言不仅可以编写“黑屏”的控制台程序,还可以编写拥有漂亮界面的Windows程序(GUI程序),只是绝大多数C语言教程都没有告诉你而已,让你以为C语言程序只能是“黑乎乎”的。

开发 GUI 程序需要选择的项目类型是“Win32项目”,其他操作和控制台程序一样。

C语言入门教程,C语言学习教程(第二部分:C语言初探)二_第32张图片

第一个带界面的C语言程序:

#include

int WINAPI WinMain(

        HINSTANCE hInstance,

        HINSTANCE hPrevInstance,

        LPSTR lpCmdLine,

        int nCmdShow

){

        int nSelect = MessageBox(NULL, "你好,欢迎来到C语言中文网!", "Welcome", MB_OKCANCEL | MB_ICONEXCLAMATION);

        return 0;

}

运行结果:

C语言入门教程,C语言学习教程(第二部分:C语言初探)二_第33张图片

你看,弹出一个带界面的欢迎窗口。控制台程序以main为入口函数,Windows程序以WinMain为入口函数。

上面的例子仅仅是一个提示框,下面我们来创建一个真正的窗口:

#include

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

int WINAPI WinMain(

        HINSTANCE hInstance,

        HINSTANCE hPrevInstance,

        PSTR szCmdLine,

        int iCmdShow

){

         static TCHAR szAppName[] = TEXT("HelloWin");

         HWND           hwnd;

         MSG              msg;

         WNDCLASS  wndclass;

         wndclass.style                  = CS_HREDRAW | CS_VREDRAW;

         wndclass.lpfnWndProc     = WndProc;

         wndclass.cbClsExtra        = 0;

         wndclass.cbWndExtra      = 0;

         wndclass.hInstance          = hInstance ;

         wndclass.hIcon                 = LoadIcon (NULL, IDI_APPLICATION);

         wndclass.hCursor             = LoadCursor (NULL, IDC_ARROW);

         wndclass.hbrBackground  = (HBRUSH) GetStockObject (WHITE_BRUSH);

         wndclass.lpszMenuName  = NULL ;

         wndclass.lpszClassName  = szAppName ;

         if( !RegisterClass(&wndclass) ){

                MessageBox(

                        NULL,

                        TEXT("This program requires Windows NT!"),

                        szAppName,

                        MB_ICONERROR

                );

        return 0 ;

                }

        // creation parameters

        hwnd = CreateWindow(

                szAppName, // window class name

                TEXT("Welcome"), // window caption

                WS_OVERLAPPEDWINDOW, // window style

                CW_USEDEFAULT, // initial x position

                CW_USEDEFAULT, // initial y position

                500, // initial x size

                300, // initial y size

                NULL, // parent window handle

                NULL, // window menu handle

                hInstance, // program instance handle

                NULL

        );

        ShowWindow (hwnd, iCmdShow) ;

        UpdateWindow (hwnd) ;

        while( GetMessage(&msg, NULL, 0, 0) ){

                TranslateMessage(&msg);

                DispatchMessage (&msg);

        }

        return msg.wParam;

        }

LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam){

        HDC hdc;

        PAINTSTRUCT ps;

        RECT rect;

        switch (message){

                case WM_PAINT:

                        hdc = BeginPaint (hwnd, &ps) ;

                        GetClientRect (hwnd, &rect) ;

                        DrawText(

                                hdc,

                                TEXT("你好,欢迎来到C语言中文网"),

                                -1,

                                &rect,

                                DT_SINGLELINE | DT_CENTER | DT_VCENTER

                        ) ;

                        EndPaint (hwnd, &ps) ;

                        return 0 ;

                case WM_DESTROY:

                        PostQuitMessage(0) ;

                        return 0 ;

        }

        return DefWindowProc(hwnd, message, wParam, lParam) ;

}

运行结果:

C语言入门教程,C语言学习教程(第二部分:C语言初探)二_第34张图片

你看,创建一个简单的窗口就需要这么多C语言代码,根本记不住,学起来太吃力了。

实际开发中,我们一般不使用这种粗暴的方式创建GUI程序,而是使用 C/C++ 的界面库,它们已经把这些繁杂琐碎的代码给封装好了,让我们“站在了巨人的肩上”,例如针对C语言的 GTK,针对C++的 MFC、Qt、Duilib 等。

你可能感兴趣的:(C语言入门,算法,c语言,开发语言)