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. [转载]C# 中Web.config文件的读取与写入

    asp.net2.0新添加了对web.config直接操作的功能.开发的时候有可能用到在web.config里设置配置文件,其实是可以通过程序来设置这些配置节的. asp.net2.0需要添加引用: ...

  2. c/c++中一些高级函数的使用

    setvbuf 函数名: setvbuf 功 能: 把缓冲区与流相关 用 法: int setvbuf(FILE *stream, char *buf, int type, unsigned size ...

  3. python脚本工具-1 制作爬虫下载网页图片

    参考:http://www.cnblogs.com/fnng/p/3576154.html 本文参考虫师的博客“python实现简单爬虫功能”,整理分析后抓取其他站点的图片并下载保存在本地. 抓取图片 ...

  4. 使用ANT打包Android应用

    大家好,今天来分享一下如何使用ANT打包Android应用. 通常我们习惯用eclipse来开发Android程序,它会自动帮我们打包当前的应用程序.如果在Navigator视图下,我们可以看到以下几 ...

  5. 分享10个Js的小型库,效果真的很棒

    1.$fx()简介:$fx()是一个轻量级的动画库,一些复杂的动画,可以由多个简单的动画效果进行组合,但是提供的是混淆压缩过的代码,对于研究动画源码的朋友可能特别不爽API:http://fx.ine ...

  6. [POJ 2461] Billiard

    同swustoj 11 Billiard Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 1362   Accepted: 8 ...

  7. [swustoj 679] Secret Code

    Secret Code 问题描述 The Sarcophagus itself is locked by a secret numerical code. When somebody wants to ...

  8. apache开源项目--lume

    lume 是一个分布式.可靠和高可用的服务,用于收集.聚合以及移动大量日志数据,使用一个简单灵活的架构,就流数据模型.这是一个可靠.容错的服务.

  9. 【转】 C++中如何在一个构造函数中调用另一个构造函数

    在C++中,一个类的构造函数没法直接调用另一个构造函数,比如: #ifndef _A_H_ #define _A_H_ #include <stdio.h> #include <ne ...

  10. vim配色方案

    想更换vim配色方案,需要修改两个文件: 第一个修改是在 /user/share/vim/vim73/colors 添加xxx.vim文件://路径里面有些不是vim73,是vim70或其他 第二个修 ...