1.       预处理程序 
按照ANSI标准的定义,预处理程序应该处理以下指令: 
#if 
#ifdef 
#ifndef 
#else 
#elif 
#endif 
#define 
#undef 
#line 
#error 
#pragma 
#include 
显然,上述所有的12个预处理指令都以符号#开始,,每条预处理指令必须独占一行。 
2.       #define 
#define指令定义一个标识符和一个串(也就是字符集),在源程序中发现该标识符时,都用该串替换之。这种标识符称为宏名字,相应的替换称为宏代换。一般形式如下: 
#define macro-name char-sequence 
这种语句不用分号结尾。宏名字和串之间可以有多个空白符,但串开始后只能以新行终止。 
例如:我们使用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-message 
注意,宏串error-message不用双引号包围。遇到#error指令时,错误信息被显示,可能同时还显示编译程序作者预先定义的其他内容。 
4.       #include 
程序中的#include指令要求编译程序读入另一个源文件。被读入文件的名字必须用双引号(“”)或一对尖括号(<>)包围,例如: 
#include “stdio.h” 
#include <stdio.h> 
都使C编译程序读入并编译头文件以用于I/O系统库函数。 
包含文件中可以包含其他#include指令,称为嵌套包含。允许的最大嵌套深度随编译器而变。 
文件名被双括号或尖括号包围决定了对指定文件的搜索方式。文件名被尖括号包围时,搜索按编译程序作者的定义进行,一般用于搜索某些专门放置包含文件的特殊目录。当文件名被双括号包围时,搜索按编译程序实时的规定进行,一般搜索当前目录。如未发现,再按尖括号包围时的办法重新搜索一次。 
通常,绝大多数程序员使用尖括号包围标准的头文件,双引号用于包围与当前程序相关的文件名。

5.       条件编译指令 
若干编译指令允许程序员有选择的编译程序源代码的不同部分,这种过程称为条件编译。 
5.1#if、#else、#elif #endif 
条件编译指令中最常用的或许是#if,#else,#elif和#endif。这些指令允许程序员根据常数表达式的结果有条件的包围部分代码。 
#if的一般形式是: 
#if constant-expression 
Statement sequence 
#endif 
如#if后的常数表达式为真,则#if和#endif中间的代码被编译,否则忽略该代码段。#endif标记#if块的结束。

#else指令的作用与C语言的else相似,#if指令失败时它可以作为备选指令。例如: 
#include <stdio.h> 
#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 expression 
Statement sequence 
#elif expression1 
Statement sequence 
#elif expression2 
Statement sequence 



#elif expression 
Statement sequence 
#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 <stdio.h> 
#define T 10

Int main(void) 

#ifdef t 
Printf(“Hi T\n”); 
#else 
Printf(“Hi anyone\n”); 
#endif 
#ifndef M 
Printf(“M Not Defined\n”); 
#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__都是编译程序中预定义的标识符。标识符__LINE__的内容是当前被编译代码行的行号,__FILE__的内容是当前被编译源文件的文件名。#line的一般形式是: 
#line number “filename” 
其中,number是正整数并变成__LINE__的新值;可选的“filename”是合法文件标识符并变成__FILE__的新值。#line主要用于调试和特殊应用。

9.       #pragma 
#pragma是编译程序实现时定义的指令,它允许由此向编译程序传入各种指令。例如,一个编译程序可能具有支持跟踪程序执行的选项,此时可以用#pragma语句选择该功能。编译程序忽略其不支持的#pragma选项。#pragma提高C源程序对编译程序的可移植性。 
10. 预处理操作符#和## 
有两个预处理操作符:#和##,它们可以在#define中使用。 
操作符#通常称为字符串化的操作符,它把其后的串变成用双引号包围的串。例如: 
#include <stdio.h> 
#define mkstr(s) #s 
int main(void) 

Printf(mkstr(I like C));

Return 0; 
}

预处理程序把以下的语句: 
Printf(mkstr(I like C)); 
变成 
Printf(“I like C”); 
操作符##把两个标记拼在一起,形成一个新标记。例如: 
#include <stdio.h> 
#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__ 
__TIME__ 
__STDC__

__LINE__和__FILE__包含正在编译的程序的行号和文件名。 
__DATE__和内容形如month/day/year(月/日/年)的串,代表源文件翻译成目标码的日期。 
__TIME__中的串代表源代码编译成目标码的时间,形如hour:minute:second(时:分:秒) 
如果__STDC__的内容是十进制常数1,则表示编译程序的实现符合标准C。 

C/C++编译预处理命令详解【转】的更多相关文章

  1. C语言预处理命令详解

    一  前言 预处理(或称预编译)是指在进行编译的第一遍扫描(词法扫描和语法分析)之前所作的工作.预处理指令指示在程序正式编译前就由编译器进行的操作,可放在程序中任何位置. 预处理是C语言的一个重要功能 ...

  2. #pragma预处理命令详解

    #pragma预处理命令 #pragma可以说是C++中最复杂的预处理指令了,下面是最常用的几个#pragma指令: #pragma comment(lib,"XXX.lib") ...

  3. [转]C语言预处理命令详解

    转载:https://www.cnblogs.com/clover-toeic/p/3851102.html 一  前言 预处理(或称预编译)是指在进行编译的第一遍扫描(词法扫描和语法分析)之前所作的 ...

  4. (61)C语言预处理命令详解

    一  前言 预处理(或称预编译)是指在进行编译的第一遍扫描(词法扫描和语法分析)之前所作的工作.预处理指令指示在程序正式编译前就由编译器进行的操作,可放在程序中任何位置. 预处理是C语言的一个重要功能 ...

  5. Android 6.0 RK3288 ROM编译详解+命令详解【转】

    本文转载自:http://blog.csdn.net/MLQ8087/article/details/58607692 Android 6.0 RK3288 ROM编译详解+命令详解 原创 2017年 ...

  6. #pragma 预处理指令详解

    源地址:http://blog.csdn.net/jx_kingwei/article/details/367312 #pragma  预处理指令详解              在所有的预处理指令中, ...

  7. C#中的预处理指令详解

    这篇文章主要介绍了C#中的预处理指令详解,本文讲解了#define 和 #undef.#if.#elif.#else和#endif.#warning和#error.#region和#endregion ...

  8. pragma comment的使用 pragma预处理指令详解

    pragma comment的使用 pragma预处理指令详解   #pragma comment( comment-type [,"commentstring"] ) 该宏放置一 ...

  9. VC编译连接选项详解

    VC编译连接选项详解 大家可能一直在用VC开发软件,但是对于这个编译器却未必很了解.原因是多方面的.大多数情况下,我们只停留在“使用”它,而不会想去“了解”它.因为它只是一个工具,我们宁可把更多的精力 ...

随机推荐

  1. MVC 自定义AuthorizeAttribute 实现权限验证

    MVC内置的AuthorizeFilter先于Action/Result过滤器执行,为网站权限验证提供了很好的一套验证机制. 通过自定义的AuthorizeAttribute可以实现对用户权限的验证. ...

  2. 团体程序设计天梯赛-练习集L2-005. 集合相似度

    L2-005. 集合相似度 时间限制 400 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 陈越 给定两个整数集合,它们的相似度定义为:Nc/Nt*1 ...

  3. Generating Huge reports in JasperReports

    There are certain things to care while implementing the Jasper Reports for huge dataset to handle th ...

  4. 【leetcode】Palindrome Number (easy)

    Determine whether an integer is a palindrome. Do this without extra space. Some hints: Could negativ ...

  5. HDU4628+状态压缩DP

    /* 状态压缩DP dp[ i ]:达到i状态的最小step. 题意:每次可以去掉一个回文串,求最少几步能取完. */ #include<stdio.h> #include<stri ...

  6. Java 垃圾回收机制

    1.delete是C++里面用于释放内存的运算符,而不是Java. 2.当发现某个对象的引用计数为0时,就将对象列入待回收列表中,并不是马上予以销毁. 3.System.gc()仅仅是一个回收请求,J ...

  7. tomcat 禁止某些文件(夹)的访问

    tomcat 禁止某些文件(夹)的访问 <!-- 不允许访问的文件以及文件夹 --> <security-constraint> <display-name>Tom ...

  8. struts2+jquery+ajax实现上传&&校验实例

    一直以为ajax不能做上传,直到最近看了一些文章.需要引入AjaxFileUploaderV2.1.zip,下载链接:http://pan.baidu.com/s/1i3L7I2T 代码和相关配置如下 ...

  9. Silverlight之Styles和Behaviors

    本文简介 1.定义简单的Style 2.应用Style到元素 3.动态加载Style资源文件 4.Style的继承 5.组织内编写Style(在元素内) 6.自动应用Style到指定类型元素 7.St ...

  10. A simple json-rpc case for bitcoin blockchains

    #!/usr/bin/env python import json import jsonrpc import requests #url = "http://user:password@i ...