apue学习第七天(1)——# in C/C++(C/C++中的井号)

终于又回来啦!元旦假期陪同学玩了两天,今天要回归正轨了!

直接进入正题:在图3-11中有一段代码不怎么明白:

#if !defined(_POSIX_C_SOURCE) ...
      ...
#endif

学了那么多年计算机,我也是挺懒的,碰到过很多次这样的语句,每次都是不求甚解的略过。今天呐,又拦在路上,索性解决它吧!

我想,几乎所有学习C/C++的童鞋第一次写代码打的第一个字符就是这个#了,多么重要的意义啊!可惜它又是多么得容易被忽略啊!好了,废话不多说,下面开始介绍#。


首先,这个#是谁用它呢?用在哪里呢?答案是:the C Preprocessor。

The C preprocessor modifies a source code file before handing it over to the compiler. 知道了吧,预处理器嘛,就是第一阶段预处理的工作。关于preprocessor,它主要的使用包括三种:directives、constents、macros,也就是指令、常量和宏,来看:

1. include files

这个不用说了,#include都知道,也就是头文件,注意" "一般是自定义头文件,< >一般是库头文件,其它的都没必要说了;

2. constents

#define [identifier name] [value]

就像#define PI_PLUS_ONE (3.1415926 + 1),这个value值可以定义成一个数,也可以定义成一个数学表达式,就像这个示例,但这儿请注意,请用括号把它括起来,因为#define在预处理中只是简单的替换操作,不括起来的话容易发生像macro一样的错误,这种错误下面讲宏的时候会说;

3. conditional compilation 条件编译

这些#if #ifndef #else这些options可以被preprocessor用来决定在将代码交付compiler之前是否删除其中的代码。

1)commenting out code 给代码添加注释

这是个很有意思的用途,比如说像下面这段代码,其实条件编译语句是无用的,用途只是来添加一些注释,然而,这个用途被很多人所喜好。

#if 0
/* comment ...
*/

// code

/* comment */
#endif

2)Include guards

#ifndef _FILE_NAME_H_
#define _FILE_NAME_H_

/* code */

#endif // #ifndef _FILE_NAME_H_

这个我不知道该怎么翻译,功能是这句话:The preprocessor provides a technology for ensuring that any given file is included once and only once.意思是,比如说在一个工程中一个头文件被很多头文件都include进去了,但这根本没必要。举例说,有a.h, b.h和main.c三个文件,main中同时#include a.h和b.h,同时b.h在开头include了a.h,那么按照顺序,在mainpreprocess的时候会include a.h, a.h, b.h,这样看来,a.h被include了两遍!但如果头文件开头和结尾都加上#ifndef这些东西,那么就只会include一遍! 这里有个很精彩的解释:http://stackoverflow.com/questions/8020113/c-include-guards。所以说,这也就是Guard这个词的由来啦!

下面有个更简单的例子帮助理解:

#ifndef NULL      //if not define;
#define NULL (void *)0
#endif // #ifndef NULL

如果没有define NULL的话,那就define好啦。


4. macro 宏

这算是我们学C以来遇到的最高大上的词啦,宏,第一次听到的感觉就是:完全无法按照汉语意思去理解嘛!

看macro,肯定首先要从什么是macro来看了。In computers, a macro (for "large"; the opposite of "micro") is any programming or user interface that, when used, expands into something larger.好啦,看到了吧,宏,按照古汉语来说是名词用做动词,字面上讲就是把代码扩展出去。In assembler language, a macro definition defines how to expand a single language statement or computer instruction into a number of instructions. ok,这下对“宏”这个翻译肯定是明白了,那么继续来看macro。

macro不需要函数调用,直接替换掉代码,看起来很方便吧!但是,什么都是双刃剑啊!看下面的代码:

#define MULT(x, y) x * y
int z = MULT(3 + 2, 4 + 2);
int z = 3 + 2 * 4 + 2;    // 2 * 4 will be evaluated first!

你想要的结果是多少?实际算出来的结果是多少?看到弊端了吧!并且这种弊端并不是加一两个括号就能解决的,还有很多其它例子我就不一一列举了。所以说,能避免尽量避免吧!可用的东西还是很多的,比如说,templete functions等等。

本文的主体内容来自:http://www.cprogramming.com/tutorial/cpreprocessor.html。

下面是长长的分割线

———————————————————————————————————————————————————

好啦,上面关于#说的已经很清楚啦,“宏”这个曾经高大上的词语也看起来摇摇欲坠了。




你可能感兴趣的:(apue学习第七天(1)——# in C/C++(C/C++中的井号))