C语言的预处理命令有哪些?_c语言预处理命令篇
C语言的预处理命令有哪些?由刀豆文库小编整理,希望给你工作、学习、生活带来方便,猜你可能喜欢“c语言预处理命令篇”。
问:关于C语言中的预处理命令? 答:
我们可以在C源程序中插入传给编译程序的各种指令,这些指令被称为预处理器指令(等价于汇编语言中的伪指令),它们扩充了程序设计的环境。
现把常用的预处理命令总结如下:
1.预处理程序
按照ANSI标准的定义,预处理程序应该处理以下12条指令:
#if、#ifdef、#ifndef、#else、#elif、#endif、#define、#undef、#line、#error、#pragma、#include。
显然,所有的12个预处理指令都以符号#开始,每条预处理指令必须独占一行。2.#define #define指令定义一个标识符和一个串(也就是字符集),在源程序中发现该标识符时,都用该串替换之(原样替换,不要附加任何人为理解上的符号)。这种标识符称为宏名字,相应的替换称为宏代换。一般形式如下:
#define macro-name char-sequence 这种语句不用分号结尾。宏名字和串之间可以有多个空格符,但串开始后只能以新行终止。在C语言里宏定义只用来做的宏名替换,而不做语法检查的,因而它不是C语句,所以宏定义的语句结尾不需要加分号。
宏也在C里也叫预处理命令,因为宏是在程序编译前先进行字符替换的,所以叫预处理.例如:我们使用LEFT代表1,用RIGHT代表0,我们使用两个#define指令:
#define LEFT 1 #define RIGHT 0 每当在源程序中遇到LEFT或RIGHT时,编译程序都用1或0替换。定义一个宏名字之后,可以在其他宏定义中使用,例如:
#define ONE 1 #define TWO ONE+ONE #define THREE ONE+TWO 宏代换就是用相关的串替代标识符。因此,如果希望定义一条标准错误信息时,可以如下定义:
#define ERROR_MS “Standard error on input n” 如果一个串长于一行,可在行尾用反斜线””续行,如下:
#define LONG_STRING “This is a very very long
string that is used as an example”
3.#error
#error指令强制编译程序停止编译,它主要用于程序调试(放在错误的分支中,一旦进入错误的分支就显示该信息)。
#error指令的一般形式是:
#error error-meage 注意,宏串error-meage不用双引号包围。遇到#error指令时,错误信息被显示,可能同时还显示编译程序作者预先定义的其他内容。
4.#include 程序中的#include指令要求编译程序读入另一个源文件。被读入文件的名字必须用双引号(“”)或一对尖括号()包围,例如:
#include “stdio.h” #include 都使C编译程序读入并编译头文件以用于I/O系统库函数。
包含文件中可以包含其他#include指令,称为嵌套包含。允许的最大嵌套深度随编译器而变。文件名被双括号或尖括号包围决定了对指定文件的搜索方式。文件名被尖括号包围时,搜索按编译程序作者的定义进行,一般用于搜索某些专门放置包含文件的特殊目录。当文件名被双引号包围时,搜索按编译程序实时的规定进行,一般搜索当前目录。如未发现,再按尖括号包围时的办法重新搜索一次。
通常,绝大多数程序员使用尖括号包围标准的头文件,双引号用于包围与当前程序相关的文件名。
5.条件编译指令
若干编译指令允许程序员有选择的编译程序源代码的不同部分,这种过程称为条件编译。5.1 #if、#else、#elif #endif 条件编译指令中最常用的或许是#if,#else,#elif和#endif。这些指令允许程序员根据常数表达式的结果有条件地启用(包围)部分代码。
#if的一般形式是:
#if constant-expreion Statement sequence #endif 如#if后的常数表达式为真,则#if和#endif中间的代码被编译,否则忽略该代码段。#endif标记#if块的结束。
#else指令的作用与C语言的else相似,#if指令失败时它可以作为备选指令。例如:
#include #define MAX 100 Int main(void){
#if MAX>99 printf(“Compiled for array greater than 99.n”);#else printf(“Complied for small array.n”);#endif return 0;} 注意,#else既是标记#if块的结束,也标记#else块的开始。因为每个#if只能写一个#endif匹配。#elif指令的意思是“否则,如果”,为多重编译选择建立一条if-else-if(如果-否则-如果链)。如果#if表达式为真,该代码块被编译,不测试其他#elif表达式。否则,序列中的下一块被测试,如果成功则编译之。一般形式如下:
#if expreion 1 Statement sequence 1 #elif expreion 2 Statement sequence 2 #elif expreion 3 Statement sequence 3 …
#elif expreion n Statement sequence n #endif 5.2 #ifdef 和 #ifndef
条件编译的另一个方法是使用编译指令#ifdef和#ifndef,分别表示“如果已定义”和“如果未定义”。#ifdef的一般形式如下:
#ifdef macro-name Statement sequence #endif 如果macro-name原先已经被一个#define语句定义,则编译其中的代码块。#ifndef的一般形式是:
#ifndef macro-name Statement sequence #endif 如果macro-name当前未被#define语句定义,则编译其中的代码块。
我认为,用这种方法可以很方便的开启/关闭整个程序的某项特定功能。
?? #ifdef和#ifndef都可以使用#else或#elif语句。
#inlucde #define T 10 Int main(void){ #ifdef t Printf(“Hi Tn”);#else Printf(“Hi anyonen”);#endif #ifndef M Printf(“M Not Definedn”);#endif Return 0;} 6.#undef
#undef指令删除前面定义的宏名字。也就是说,它的意思是“不要已定义的某个宏”。一般形式为:
#undef macro-name 7.使用defined 除#ifdef之外,还有另外一种确定是否定义宏名字的方法,即可以将#if指令与defined编译时操作符一起使用。defined操作符的一般形式如下:
defined macro-name 如果macro-name是当前定义的,则表达式为真,否则为假。例如,确定宏MY是否定义,可以使用下列两种预处理命令之一:
#if defined MY 或
#ifdef MY 也可以在defined之前加上感叹号”!”来反转相应的条件。例如,只有在DEBUG未定义的情况下才编译。
#if!defined DEBUG Printf(“Final Version!n”);#endif 使用defined的一个原因是,它允许由#elif语句确定的宏名字存在。??? 8.#line #line指令改变__LINE__和__FILE__的内容。__LINE__和__FILE__都是编译程序中预定义的标识符(见11)。标识符__LINE__的内容是当前被编译代码行的行号,__FILE__的内容是当前被编译源文件的文件名。#line的一般形式是:
#line number “filename”
其中,number是正整数并变成__LINE__的新值;可选的“filename”是合法文件标识符并变成__FILE__的新值。#line主要用于调试和特殊应用。
9.#pragma
#pragma是编译程序实现时定义的指令,它允许由此向编译程序传入各种指令。例如,一个编译程序可能具有支持跟踪程序执行的选项,此时可以用#pragma语句选择该功能。编译程序忽略其不支持的#pragma选项。#pragma提高C源程序对编译程序的可移植性。
10.预处理操作符#和## 有两个预处理操作符:#和##,它们可以在#define中使用。
操作符#通常称为字符串化的操作符,它把其后的串变成用双引号包围的串。例如: #include #define mkstr(s)#s int main(void){ Printf(mkstr(I like C));Return 0;} 预处理程序把以下的语句: Printf(mkstr(I like C));变成Printf(“I like C”);
操作符##把两个标记拼在一起,形成一个新标记。例如: #include #define concat(a,a)a##b int main(void){ Int xy = 10;Printf(“%d”,concat(x,y));Return 0;} 预处理程序把以下语句: Printf(“%d”,concat(x,y));变成Printf(“%d”,xy);
操作符#和##主要作用是允许预处理程序对付某些特殊情况,多数程序中并不需要。11.预定义宏
C规范了5个固有的预定义宏,它们是: __LINE__:正在编译的程序的行号 __FILE__:正在编译的程序的文件名
__DATE__:代表源文件翻译成目标码的日期,形如month/day/year(月/日/年)__TIME__:代表源代码编译成目标码的时间,形如hour:minute:second(时:分:秒)__STDC__:如果__STDC__的内容是十进制常数1,则表示编译程序的实现符合标准C。
问:在程序的一行上可以出现多个有效的预处理命令行。预处理命令可以出现在函数的内部。给出的两段代码,有一段是错误的,哪段???
答:
第1段有问题。#ifndef WIN32 #endif printf(“OKn”);在这里,这个printf就不会被执行。也就是说,一行中,只能有一条预处理指令,当编译的预处理阶段,编译器识别了一条完整的预处理指令后,后面的所有东西他都不要了。
对于第二段,在函数里,我们是可以使用预处理指令的。比如:
void fun(void){ #ifdef WIN32...// 对于windows系统环境的操作 #else...// 对于windows以外的系统环境的操作
#endif /* WIN32 */...}
问:两个C语言的小问题(预处理命令)1.#define abc(x,y)(x)
答:
1.c = 10*abc(a,b)= 10 *(x)
问:C语言预处理命令#define 选择题:以下程序的运行结果是?
#define MAX(A,B)(A)>(B)?(A):(B)#define PRINT(Y)printf(“Y=%dt”,Y)main(){ int a=1,b=2,c=3,d=4,t;t=MAX(a+b,c+d);PRINT(t);} A)Y=3 B)存在语法错误 C)Y=7 D)Y=0 请给我解释下PRINT(t);在宏展开是怎么表示的,答案是C。
答:宏处理的时候,一定要记住:直接代进去,任何多余的动作都不能有(别想当然地加括号!)。
还有记住一点的是在printf“”双括号里的是不能替代的话,所以这里的Y是输出形式。而不是字符常量Y的替代。这是一种特殊规定。
PRINT(t)=printf(“Y=%dt”,t);所以结果必将是Y=(一个值)又因为
MAX(a+b,c+d)(a+b)>(c+d)?(a+b):(c+d)的结果是7,所以,答案是“C)Y=7”。
问:求解:关于c语言中,宏定义的问题。。#define NLMSG_ALIGNTO 4 #define NLMSG_ALIGN(len)(((len)+ NLMSG_ALIGNTO1))这句编译没错,请问 NLMSG_ALIGNN(len)的值是多少
答: 1.第一句定义了一个符号常量,值为4。隐含的作用是指定地址对齐方式:按4边界对齐。
例如若某个对象的长度为18,那么在为其分配空间时,通过NLMSG_ALIGN宏就可以计算出最接近其的4的倍数为((18+4-1)& ~(3))= 20,这样便为其申请/分配20字节空间。
这是32位微控制器/微处理器中,为了防止非对齐操作产生Exception(异常)而添加的保护措施。
2.第二句定义了一个宏,宏体是一个表达式
3.NLMSG_ALIGNN(len)是宏调用,具体做法就是单纯地把字符用符号常量的值替换掉(宏展开)。宏展开的结果就是(((len)+ 41))。要说一下 &~,&是与运算,~是取反,都是对二进制“位”的操作。这里&~在一起,意思是“与3的非”。比如 5&~3 那么结果就是4(用2进制数表达就是:101&~011那么就是101&100,结果是2进制的100)。
问: 答:
问:
答: