由“源代码”到“可执行文件”的过程包括四个步骤:预编译、编译、汇编、链接。所以,首先就应该清楚的首要问题就是:预编译只是对程序的文本起作用,换句话说就是,预编译阶段仅仅对源代码的单词进行变换,而不是对程序中的变量、函数等。预编译指令的基本知识不作详细介绍,只稍作汇总,重点是后面的我能想到的使用时的注意事项。1.基本内容预编译指令基本分类如下类别指令预定义符号__FILE__、__LINE__、__DATE__、__TIME__、__STDC__宏#define文件包含#include条件编译#if、#elif、#else、#ifdef、#ifndef、#endif还有一些指令,名称和功能如下表:指令功能#空指令#undef移除一个空定义#error停止编译,并生成错误信息#line修改__LINE__和__FILE__的值#progma允许编译器提供额外功能在定义宏的时候,有两个运算符:运算符功能#将宏参数转换为字符串##将多个符号连接成一个标识符2.宏定义1.一般在宏定义的结尾不加分号。我们在使用的时候,要加上分号,像我们平时写语句一样。2.注意加括号。在有参数的空定义中,如果含有数值运算,那么就要在“宏整体”和“宏参数”两端都要加上括号。如:#definemax(a,b)((a)+(b));3.注意空格。在有参数的宏定义中,注意“宏名称”和“参数列表”之间不能有空格。如:#definemax(a,b)((a)+(b));在max”和”(a,b)”之间不能有空格。4.不要使用有副作用的参数区调用宏。常见的有副作用的参数有:a++,getchar()等。如:宏定义为#definemax(a,b)((a)+(b));那么使用max(i++,j++)调用该宏,会造成i或j中的一个值增加2,而不是我们期望的1。5.可以使用编译器选项添加宏和移除宏。我使用的是gcc,添加宏的指令是”-D”,移除宏的指令是”-U”。6.宏参数替换的时候,不会替换字符串中的字符。即不会替换双引号之间的字符,其他的都会被替换,包括单引号之间的。7.可以使用#将宏参数的值转化为字符串。直接使用#,是将宏参数的名称转化为字符串。利用下面的技巧(增加一个过渡宏),可以将“宏参数的值”转化为字符串(当宏参数有值时,这时的宏参数常常也是一个宏)。[cpp]viewplaincopy#includestdio.h#includestdlib.h#defineNUMBERten/*宏名称为NUMBER,宏的值为ten*/#defineStr(x)#x#defineXStr(x)Str(x)/*增加的一个过渡宏*/intmain(){printf(Str(NUMBER)==%s/n,Str(NUMBER));printf(XStr(NUMBER)==%s/n,XStr(NUMBER));system(pause);returnEXIT_SUCCESS;}输出结果为:[cpp]viewplaincopyStr(NUMBER)==NUMBERXStr(NUMBER)==ten8.使用##运算符来实现标识符连接。不过,不建议使用操作符##来连接标识符,因为这个容易是程序可读性大大降低。3.文件包含1.要将头文件的定义在保护条件中。目的是为了防止重复包含头文件。如果你查看过gcc或者其他编译器的源代码,你一定对这个非常熟悉。例如,你要编写一个头文件,myheader.h,那么你的头文件的内容形式应该为:(定义一个_MYHEADER宏)[cpp]viewplaincopy#ifndef_MYHEADER#define_MYHEADER1/*中间是你的头文件内容*/#endif/*_MYHEADER*/2.注意windows系统和Unix系统的路径符号不同。可以再#include中指定路径来包含文件,例如#include“../head.h”。但是注意,windows中使用反斜线”/”作为路径分隔符,而Unix系统使用的是斜线”/”。3.可以使用编译器选项来设置搜索路径。我使用的gcc,使用的-Idir选项,例如:-ID:/Dev-Cpp/include。4.条件编译1.#ifdef等价于#ifdefined(),#ifndef等价于#if!defined()。2.在#if中可以使用逻辑操作符(、
、!)。在#ifdef中是不可以使用的,这也是#if的优越点。[cpp]viewplaincopy#includestdio.h#includestdlib.h#defineA1#defineB0intmain(){#ifdefined(A)defined(B)printf(testlogicoperationin#if/n);/*如果上面的逻辑判断成立,那么将打印出一句话;如果不成立,那么就不会打印这句话*/#endifsystem(pause);returnEXIT_SUCCESS;}运行结果:[cpp]viewplaincopytestlogicoperationin#if3.sizeof(int)在预编译阶段是不会被求值的。只要知道“预编译阶段”在真正的“编译阶段”之前,就很容易理解了。预编译阶段只是对组成源代码中的字符进行作用,从某种意义上来说,它有时甚至不知道它的操作对象是什么,它只是按照既定的规则执行替换。sizeof(int),无论是sizeof的解析,还是类型的解析,都是在“编译阶段”才开始的,编译阶段知道它的操作对象是什么。下面的代码是错误的[cpp]viewplaincopy#ifsizeof(int)==2printf(pre
转载请注明:http://www.0431gb208.com/sjszjzl/7728.html
上一篇文章: C语言从入门到熟练掌握
下一篇文章: 没有了