转:C++中 #ifdef 和#endif的作用
一般情况下,源程序中所有的行都参加编译。但是有时希望对其中一部分内容只在满足一定条件才进行编译,也就是对一部分内容指定编译的条件,这就是“条件编译”。有时,希望当满足某条件时对一组语句进行编译,而当条件不满足时则编译另一组语句。
条件编译命令最常见的形式为:
#ifdef 标识符
程序段1
#else
程序段2
#endif
它的作用是:当标识符已经被定义过(一般是用#define命令定义),则对程序段1进行编译,否则编译程序段2。
其中#else部分也可以没有,即:
#ifdef
程序段1
#denif
在头文件中使用#ifdef和#ifndef是非常重要的,可以防止双重定义的错误。如你在头文件aaa.h中定义了一个类aaa如下:
class aaa
{
};
如果两次#include "aaa.h"(不见得是直接,也有可能两个不同的头文件中都包含了这个头文件)就会出错,因为相同的类不能定义两次。把aaa.h稍做修改:
#ifndef _aaa_
#define _aaa_
class aaa
{
};
#endif
就可以避免这样的问题。因为当你已经包含过这个文件,_aaa_就会有了定义,那么#ifndef的条件为假,就不会再执行后面的类定义了。
#ifdef和#endif必须成对使用。
从理论上讲可以出现在任何地方(头文件和实现文件中)
通常为了防止头文件被多次包含,在头文件中使用是必须的:
如:#ifndef MY_HEAD_H //头文件开头,名字是任意的,注意不要和其它头文件冲突
头文件声明
#endif //头文件结尾
有时候,在b.h中会include "a.h" ,在"c.h"中会include "b.h"及include"a.h", 这时,如果不用ifndef/endif,就会包含两次a.h,产生错误。
还是把头文件的内容都放在#ifndef和#endif中吧。不管你的头文件会不会被多个文件引用,你都要加上这个。一般格式是这样的:
#ifndef <标识>
#define <标识>
......
......
#endif
<标识>在理论上来说可以是自由命名的,但每个头文件的这个“标识”都应该是唯一的。标识的命名规则一般是头文件名全大写,前后加下划线,并把文件名中的“.”也变成下划线,如:stdio.h
#ifndef _STDIO_H_
#define _STDIO_H_
......
#endif
2.在#ifndef中定义变量出现的问题(一般不定义在#ifndef中)。
#ifndef AAA
#define AAA
...
int i;
...
#endif
里面有一个变量定义,在vc中链接时就出现了重复定义的错误,而在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;
注意问题:
(1).变量一般不要定义在.h文件中。
下面是一个例子:编译后出现的错误---------fatal error C1189: #error : WINDOWS.H already in
种情况本质上就是对windows.h头文件重复引用,解决的办法,如果能不引用此头文件当然就不要引用,如果非得引用,或者是引用其他头文件导致的间接引用windows.h,那么不要在stdafx.h文件里面引用,一般可以解决。
或者可使用如下代码:
所以使用如下代码:
#ifdef _WINDOWS_
#undef _WINDOWS_
#endif
或者#ifndef #define #endif
如果还不行,就换一下头文件位置,#include "stdafx.h"放在#include <windows.h>之前
转于 http://www.cnblogs.com/renyuan/archive/2013/05/22/3092362.html
转:C++中 #ifdef 和#endif的作用的更多相关文章
- C++中 #ifdef 和#endif的作用
一般情况下,源程序中所有的行都参加编译.但是有时希望对其中一部分内容只在满足一定条件才进行编译,也就是对一部分内容指定编译的条件,这就是"条件编译".有时,希望当满足某条件时对一组 ...
- 【转载】C/C++中#ifdef和#endif的用法
转于 http://www.cnblogs.com/renyuan/archive/2013/05/22/3092362.html 今天笔试的时候遇到这个问题,整理一下! 一般情况下,源程序中所有的行 ...
- c/c++ 中#ifndef和#endif的作用及使用
有时候我们在编程的时候,希望有些代码在我们需要时编译,不需要时不编译,也就是让它快速注释,这时候即可以考虑#ifdef和#endif,它们会使我们的编译器进行选择性编译.使用方法如下: #includ ...
- 头文件中ifndef/define/endif的作用以及#pragma once使用
例如:要编写头文件test.h 在头文件开头写上两行: #ifndef _TEST_H #define _TEST_H//一般是文件名的大写 ············ ············ 头文件 ...
- #ifdef __cplusplus extern c #endif 的作用
#ifdef __cplusplus // C++编译环境中才会定义__cplusplus (plus就是"+"的意思) extern "C" { // 告诉编 ...
- C语言中#ifdef,#ifndef和#endif的作用
现在规定一下头文件书写规范, 根据陈皓编写的跟我一起些makefile,一定要记住:头文件中应该只是声明,而定义应该放在C/C++文件中.否则如果出现有定义,比如头文件中有int a =2;如果有多个 ...
- #ifdef _DEBUG/ #define new DEBUG_NEW/ #endif的作用
转载:https://blog.csdn.net/minghui_/article/details/80748142 转自:#ifdef _DEBUG #define new DEBUG_NEW #e ...
- ifndef/define/endif 的作用
转载自百度百科 ,感谢度娘 1 2 3 #ifdef语句1 //程序2 #endif 可翻译为:如果宏定义了语句1则执行程序2. 作用:我们可以用它区隔一些与特定头文件.程序库和其他文件版本有关的代码 ...
- C语言预处理命令之条件编译(#ifdef,#else,#endif,#if等)
转自:http://www.kuqin.com/language/20090806/66164.html 预处理过程扫描源代码,对其进行初步的转换,产生新的源代码提供给编译器.可见预处理过程先于编译器 ...
随机推荐
- WinForm中TextBox 中判断扫描枪输入与键盘输入
本文转载:http://www.cnblogs.com/Hdsome/archive/2011/10/28/2227712.html 提出问题:在收货系统中,常常要用到扫描枪扫描条码输入到TextBo ...
- OPENSHIFT MYSQL使用Navicat连接配置
最近一直在研究openshift免费空间的使用,对于如何用本地的数据库工具连接一直在找方法,呵呵,初学者. 以下方法可以实现: 1.在本地命令行中执行命令:rhc port-forward 应用名 如 ...
- android 38 Abdroid客户端和服务端交互
服务端: package com.sxt.day05; import java.io.IOException; import java.util.ArrayList; import javax.ser ...
- innodb结构解析工具---innodb_ruby
1.下载ruby并安装ruby: ftp://ftp.ruby-lang.org/pub/ruby/ ftp://ftp.ruby-lang.org/pub/ruby/ruby-2.3-stable. ...
- 使用fastjson前台报406的问题解决方法
返回的json数据前台页面报406,而后台没有报错,下面为解决方法 <?xml version="1.0" encoding="UTF-8"?> & ...
- jQuery ajax 传递数组到struts2
使用jQuery的$.ajax()方法进行异步交互时,如果传递的数据有数组(例如传输checkbox数据),Action中经常会接受不到数据. 此时应该注意一下data中数组的写法,例如: //组合成 ...
- SQL server 使用触发器跨数据库备份数据
create database TriggerTest create table transInfo2 --交易信息表 ( cardID ) not null, --卡号 transType ) no ...
- sid超过8个字符处理步骤
服务端配置如下: [oracle@p3 admin]$ cat listener.ora # listener.ora Network Configuration File: /home/oracle ...
- 十大算法---Adaboost
当我们有针对同一数据集有多个不同的分类器模型时,怎样组合它们使预测分类的结果更加准确, 针对这种情况,机器学习通常两种策略. 1 一种是bagging,一种是boosting bagging:随机对样 ...
- C++函数二义性问题,我怎么感觉编译器有偷懒嫌疑!!!
瞎扯一段,讲得不一定对.纯属学习! struct BB{ void a(){ cout << "bb's a()\n"; }}; struct B1 : public ...