学校里学不到的C语言教程之4奇怪的第一行

兰州可以治疗白癜风的医院 http://pf.39.net/bjzkbdfyy/131204/4302790.html

当我们学习C语言一定时间后,一定会很熟悉在编写各种功能代码逻辑之前一开始就会要include一堆的h头文件。例如我们大家都知道的#includestdio.h。渐渐的我们会知道,有些功能是要再引入其他的库才能使用的。比如网络开发中,一般情况下我们都要#includewinsock.h。时间久了我们一定会想知道,到底那些h文件里有什么东西可以让我们完成这些功能呢?

当那些有心的同学找到winsock.h的代码时一定会看到里面只是些函数的声明,最多再加点结构体的声明。直接把函数体写在h文件里的可能性非常之小(除非是性能需要的inline函数)。在我们失望之余一定还会惊奇的发现每个库的h文件开关都会有一行奇怪的代码,例如:

奇怪的宏定义

而这行代码就是C/C++语言里特有的宏定义。不过我们这里并不打算讨论宏的写法。单单只说说这行代码的作用。要理解这行代码的作用,我们先来看看如果我们自己来写一个函数给别人使用(或者是方便自己重用)会发生什么。

这对于一名合格的在校生也是很容易的:那就是定义一个函数,把要做的事情写在里面就行了,以后要使用相同功能时不用再重写,直接调用这个函数就行了。没错,学会写好函数就是大家走上正式的开发人员的一个标志,在编程中还不习惯将功能写成函数或者类的话那么一看就是一位新新手。好了,当我们函数越来越多时我们要怎样做呢?好,按功能分别放到各个C文件中,然后include就行。没错大家应该都知道要这样做,不过当我们这样做的时候会有个很棘手的问题:那就是函数名会报重复。即使我们只有一函数的情况下,这种事情也会发生。例如下图:

两次include就会出错

你会说,谁让你include两次同一个文件的。确实如果一个只有一个函数的文件被include进来两次的话那么它也是会引发函数已经定义过的错误警告的。但是我要说的是,这是重复定义造成的,但却并不是include两次造成的--即我们有办法include两次也正常--之所以要学会这种办法是因为C/C++的include会嵌套,在两个不同的文件中都include同一个文件就会引入这个文件两次,那么业界是怎么解决这个问题的呢?我们把socket的头文件include两次会怎样呢?见下图:

编译成功了

可以看到,两次#includewinsock.h却是成功的!这是为什么?

答案要回到socket的头文件的第一行代码上来,其实这不是一行代码,而是由三行代码组成的防代码重入模块,这是目前C语言里普遍使用的方法,代码如下:

#ifndef_WINSOCK_H#define_WINSOCK_H//所有的代码都写在这个位置#endif

这实际上是利用的C语言的宏的特性来阻止一函数或者结构体或者定义的重复声明。否则就会报已存在的错误。另外还有一个知识点是要告诉初学者的:其实本质上C语言并不知道它include的是h还是c文件。所以以上规则无论对h还是对c都都是成立的。不过话说回头,这在现在的C++环境中由于对c和cpp文件的解释不尽相同,以上的规则其实打了折扣。解决办法是加上externC的说明。关于这个externC我们以后再说吧。这篇文章大家只要记住这个通用的防止重入的做法就行了。

另外这种防止重入的做法在定义时,通常会在前面加上一个或者两个下划线,目的就是为了尽可能不能成为唯一标识。不过现在也有一些函数或者变量喜欢在前面加下划线,所以不得已,现在的做法是在后面又再补上一两个下划线。所以最终我们看到的这个防止重入的定义通常是这样__文件名_文件后缀名__,虽然初学者看来它们有些怪,不过这样做却是非常有道理而且是非常合理的。

我们今天介绍的这个功能虽然简单,不过却能很大程度上解决大型C/C++代码开发中最大的问题:编译冲突,所以大家一定要记住。在以后的实际工作中你会发现这是非常重要的一种处理方式。




转载请注明:http://www.aierlanlan.com/rzdk/2306.html