`
yxwang0615
  • 浏览: 552826 次
  • 性别: Icon_minigender_1
  • 来自: 青岛
社区版块
存档分类
最新评论

预处理命令——条件编译

阅读更多
   灵活使用#ifdef指示符,我们可以区隔一些与特定头文件、程序库和其他文件版本有关的代码,相当于一个开关,用#define定义,存在则执行#ifdef #endif块中的内容。
#include "iostream.h"
int main()
{
#ifdef DEBUG      
cout<< "Beginning execution of main()";//使用标准的输出流来做控制台的输出
#endif      
return 0;
}

运行结果为:Press any key to continue

改写代码如下:
#include "iostream.h"
#define DEBUG
int main()
{
#ifdef DEBUG      
cout<< "Beginning execution of main()";
#endif       
return 0;
}

运行结果为:Beginning execution of main()
                  Press any key to continue

更一般的情况是,#define语句是包含在一个特定的头文件中。
比如,新建头文件head.h,在文件中加入代码:
#ifndef DEBUG
#define DEBUG
#endif

代码修改如下:
#include "iostream.h"
#include "head.h" 
int main(){
#ifdef DEBUG      
cout<< "Beginning execution of main()";
#endif       
return 0;
}


运行结果如下:Beginning execution of main()
                    Press any key to continue

结论:通过使用#ifdef指示符,我们可以区分一些与特定头文件、程序库和其他文件版本有关的代码。

   预处理就是在进行编译的第一遍词法扫描和语法分析之前所作的工作。就是对源文件进行编译前,先对预处理部分进行处理,然后对处理后的代码进行编译。这样做的好处是,经过处理后的代码,将会变的很精短。
凡事以#开头的code均为预处理命令,define为宏定义命令
#define 标识符 字符串  eg:
#define CM_COMMAND_NOTE 0x000U
程序中遇到CM_COMMAND_NOTE 的地方都会由0x000U代替


条件编译的几种情况:
情况一:
#ifdef _XXX
...程序段1...
#else
...程序段2...
#endif
   这表明如果标识符XXX已被#define命令定义过,则对程序段1进行编译;否则对程序段2进行编译。

情况二:
#ifndef _XXXX
...程序段1...
#else
...程序段2...
#endif
   如果没有定义标识符XXXX,那么执行程序段1,否则执行程序段2。

情况三:
#if 常量
...程序段1...
#else
...程序段2...
#endif
   这里表示,如果常量为真(非0,随便什么数字,只要不是0),就执行程序段1,否则执行程序段2。
   这种方法可以将测试代码加进来。当需要开启测试的时候,只要将常量变1,而不要测试的时候,只要将常量变0。

情况四:
头文件中的#ifndef -->
如果有两个C文件,这两个C文件都include了同一个头文件。而编译时,这两个C文件要一同编译成一个可运行文件,于是问题来了,大量的声明冲突。这样最好把头文件的内容都放在#ifndef和#endif中。不管头文件会不会被多个文件引用,都要加上这个。

一般格式是这样的:
#ifndef <标识>
#define <标识>
......
......

#endif

<标识>在理论上来说可以是自由命名的,但每个头文件的这个“标识”都应该是唯一的。标识的命名规则一般是头文件名全大写,前后加下划线,并把文件名中的“.”也变成下划线,如:stdio.h

#ifndef _STDIO_H_
#define _STDIO_H_

......

#endif

情况五:

在#ifndef中定义变量出现的问题(一般不定义在#ifndef中)。

#ifndef AAA
#define AAA
...
int i;
...
#endif
里面有一个变量定义
在vc中链接时就出现了i重复定义的错误,而在c中成功编译。

结论:

(1).当你第一个使用这个头的.cpp文件生成.obj的时候,int i 在里面定义了当另外一个使用这个的.cpp再次[单独]生成.obj的时候,int i 又被定义然后两个obj被另外一个.cpp也include 这个头的,连接在一起,就会出现重复定义.

(2).把源程序文件扩展名改成.c后,VC按照C语言的语法对源程序进行编译,而不是C++。在C语言中,若是遇到多个int i,则自动认为其中一个是定义,其他的是声明。

(3).C语言和C++语言连接结果不同,可能(猜测)时在进行编译的时候,C++语言将全局
变量默认为强符号,所以连接出错。C语言则依照是否初始化进行强弱的判断的。(参考)

解决方法:

(1).把源程序文件扩展名改成.c。

(2).推荐解决方案:
.h中只声明 extern int i;在.cpp中定义

<x.h>
#ifndef __X_H__
#define __X_H__
extern int i;
#endif //__X_H__
<x.c>
int i;

注意问题:

变量一般不要定义在.h文件中。


转自http://hi.baidu.com/taney/blog/item/1a06abee1763d92a2df534b7.html



分享到:
评论

相关推荐

    由浅入深学C语言——基础、进阶与必做430题.崔久,蒋欣(带详细书签)

    必须两个压缩分卷part1、...第3篇是C语言高级应用,包括算法、预编译命令、文件和图形,以及预处理命令等内容;第4篇是C语言开发案例,详细讲解了C语言项目开发案例,读者在这里可以学习到C语言项目的整个开发过程。

    由浅入深学C语言——基础、进阶与必做430题.崔久,蒋欣(带详细书签).part2.rar

    必须两个压缩分卷part1、...第3篇是C语言高级应用,包括算法、预编译命令、文件和图形,以及预处理命令等内容;第4篇是C语言开发案例,详细讲解了C语言项目开发案例,读者在这里可以学习到C语言项目的整个开发过程。

    《C语言程序设计教程——基于Visual C++6.0环境》[PDF]

    较全面地讲述了C语言程序设计的基本知识,主要内容包括概述,数据类型、运算符及表达式,基本输入/输出函数,选择结构,循环结构,数组,函数,指针,编译预处理命令,结构与共用,文件和图书管理系统案例介绍等,...

    GCC入门到精通

    1. 预处理(也称预编译,Preprocessing):处理宏定义和include,并做语法检查,生成预处理文件 2. 编译(Compilation):生成后缀为.s的汇编代码 3. 汇编(Assembly):汇编代码作为输入,生成后缀名为.o的目标代码...

    c++语言程序设计(第三版)

    5.7 多文件结构和编译预处理命令 5.8 小结 习题 第6章 数组、指针与字符串 6.1 数组 6.2 指针 6.3 动态内存分配 6.4 字符串 6.5 小结 习题 第7章 继承与派生 7.1 继承与派生 7.2 访问控制 7.3 派生类的构造和析构...

    8051系列单片机C程序设计完全手册_清晰版_2-2

    6.1.4 其他预处理命令 6.2 C51编译器控制指令详解 6.2.1 源控制指令 6.2.2 列表控制指令 6.2.3 目标控制指令 6.3 C5l的高级配置文件 6.3.1 目标程序启动配置文件——STARTUP.A51. 6.3.2 CPU初始化文件——...

    8051系列单片机C程序设计完全手册_清晰版_2-1

    6.1.4 其他预处理命令 6.2 C51编译器控制指令详解 6.2.1 源控制指令 6.2.2 列表控制指令 6.2.3 目标控制指令 6.3 C5l的高级配置文件 6.3.1 目标程序启动配置文件——STARTUP.A51. 6.3.2 CPU初始化文件——...

    嵌入式Linux C编程入门(第2版) PPT

    7.1.4 条件编译 212 7.2 c语言中的内存分配 214 7.2.1 c语言程序所占内存分类 214 7.2.2 堆和栈的区别 215 7.3 嵌入式linux可移植性考虑 216 7.3.1 字长和数据类型 216 7.3.2 数据对齐 218 ...

    单片机c语言应用100例

    4.8.1常用预处理命令介绍 4.8.2实例39:宏定义应用举例 4.8.3实例40:文件包含应用举例 4.8.4实例41:条件编译应用举例 习题与实验 第5章单片机的定时器/计数器 5.1定时器,计数器的基本概念 5.2定时器/计数器的结构...

    MATLAB 7_0实用指南 (上册)

    Jalpha查找表 14.3.3示例——将数据映射到颜色或透明度 14.4选择一个alpha查找表 第15章交互操作 15.1视点和相机 15.1.1用方位角和仰角设置视点 15.1.2交互工具——相机 15.2用相机工具条进行...

    Oracle SQL高级编程(资深Oracle专家力作,OakTable团队推荐)--随书源代码

    2.13 SQL执行——总览 52 2.14 小结 53 第3章 访问和联结方法 55 3.1 全扫描访问方法 55 3.1.1 如何选择全扫描操作 56 3.1.2 全扫描与舍弃 59 3.1.3 全扫描与多块读取 60 3.1.4 全扫描与高水位线 60 3.2 ...

    谭浩强C语言程序设计,C++程序设计,严蔚敏数据结构,高一凡数据结构算法分析与实现.rar

    9 预处理命令 9.1 概述 124 9.2 宏定义 125 9.2.1 无参宏定义 126 9.2.2 带参宏定义 127 9.3 文件包含 128 9.4 条件编译 130 9.5 本章小结 10 指针 10.1 地址指针的基本概念 131 10.2 变量的指针和指向变量的指针...

    谭浩强C语言程序设计,C++程序设计,严蔚敏数据结构,高一凡数据结构算法分析与实现.rar )

    9 预处理命令 9.1 概述 124 9.2 宏定义 125 9.2.1 无参宏定义 126 9.2.2 带参宏定义 127 9.3 文件包含 128 9.4 条件编译 130 9.5 本章小结 10 指针 10.1 地址指针的基本概念 131 10.2 变量的指针和指向变量的指针...

    亮剑.NET深入体验与实战精要2

    1.5.3 预处理指令,有你更轻松 55 1.6 Visual Studio.NET 2008 实战 58 1.6.1 如何创建ASP.NET项目 58 1.6.2 如何创建Windows项目 61 1.6.3 Visual Studio.NET 2008 操作与使用技巧 61 1.6.4 常见开发调试技巧 66...

Global site tag (gtag.js) - Google Analytics