#ifdef #define #endif (避免头文件被重复包含的真正含义)

宏定义

首先在谈论正式话题之前,需要先介绍一个基础概念,也是前提,那就是宏定义。

#define demo 1
#define PI 3.14

我们都知道这样会将demo 在预处理阶段替换或者说展开为1,Pi 替换为3.14。
#define 宏定义一个标识符来表示一个常量。预处理所执行的操作就是简单的“文本”替换。

#include <stdio.h>也是这样的,即在预处理的时候先单纯地用头文件stdio.h中所有的“文本”内容替换程序中#include <stdio.h>这一行,然后再进行正式编译。

参考这个链接:

http://c.biancheng.net/view/187.html

条件编译

好了,知道这个概念以后我们就可以引入接下来这个概念,条件编译。

#if defined() || defined() || ...
#ifdef
#ifndef
#else if
#else
#endif

注意,我只是把可能遇见的所有条件编译宏列了一下,并不代表真正写的顺序就是这样。

至于#if defined#ifdef 的区别:
#if defined 就是#if 的一种用法,只不过后面跟了defined
对于#if后面需要是一个表达式,如果表达式为真则调用#if下面的代码。
比如:

#if defined(AA) || defined(BB) //和常规if一样,只是判断当前是否定义了AA,BB,用的是英文的过去时。defined 已经定义了。
#if defined(A=1) //判断变量值。一般是通过编译宏(GCC -DXXXX 这样添加。然后使得编译生效。
# 上面我们说了如果表达式为1则调用#if下面的代码。所以甚至可以写成这样
#if 1 # 这就代表永远为真。

#define  WIDE_IN_SENSOR_ZOOM_LUX    390  
code...//你的代码,可以写很多
#endif

对于#ifdef后面需要的只是这个值有没有用#define定义,并不关心define的这个值是0还是1。
比如在上面这里这个例子,就可以接着这样写:

#if defined(AA) || defined(BB) //和常规if一样,只是判断当前是否定义了AA,BB,用的是英文的过去时。defined 已经定义了。
#define  WIDE_IN_SENSOR_ZOOM_LUX    390  //你的代码,可以写很多
code...
#ifdef WIDE_IN_SENSOR_ZOOM_LUX //上面已经定义了WIDE_IN_SENSOR_ZOOM_LUX ,接着执行下面代码
code..
#endif //时刻注意每个条件都应该一个endif
#endif

还有一个区别就是,#ifdef 只能判断一个宏,如果判断多个宏只能用 #if defined() || defined () || defined ()

避免头文件被多次包含(预处理时重复include)

那么最后回到我们的正题,一般我们能在头文件看到最开始这样定义

#ifndef A_H //这个地方不需要和头文件名一样!理解这句话你就明白避免重复包含的真正含义了,而不是单纯记一个八股文知识点。
所以还可以写成
#ifndef _A_H_
#ifndef _A_H  都是一样的
...

#defined A_H
...头文件,随便写两个
#include <linux/wait.h>
#include <linux/delay.h>
...
#endif

A_H 这个宏就是开关,用一个宏变量来起到开关的作用,如果没定义过,就定义,然后往下走,include 头文件,但是如果定义过了,就不会执行下面的include。就这么简单。

上面是通常的写法,一般重复包含指的是:
我们在a.cpp中

#include "a.h" 
#include "b.h"

但是在a.h中我们又

#include "b.h"

这样在预处理阶段,展开#include "a.h" 时候会递归展开b.h, 然后#include "b.h"又展开一遍,这就是重复包含了。
虽然我们自己在写程序的时候,一般不会编译报错。因为我们写的都是小程序,并不是大型的工程,但是在大型工程中,可能会因为重复包含而编译出错。


回到上面,那么我们在头文件中使用这三行,就相当于一个开关
比如在b.h中写上这三行。那么我们第一次展开a.h时候将b.h展开,然后就会判断是否定义 B_H 这个宏,然后定义,再执行代码。

#ifndef B_H 
#defined B_H
code...
#endif

下一次再展开b.h时候,就会再次判断,#ifndef B_H 但这个时候我们已经定义过 B_H 了,就不会往下走了,直接退出。就不会再次定义,也不会再次执行下面的代码,也就是不会再次在预处理阶段展开。

也就是不会在#include "b.h" 处再次将这一行替换为头文件中代码。因为#include "b.h" 在预处理阶段会替换为头文件中代码。

总结

所以总结来说就是用条件编译定义一个宏(作为一个开关),去判断是否include当前头文件。以此避免重复定义!

  • 6
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
////////////////////////////////////////////////////////////////////// // PictureEx.cpp: implementation of the CPicture class. // // Picture displaying control with support for the following formats: // GIF (including animated GIF87a and GIF89a), JPEG, BMP, WMF, ICO, CUR // // Written by Oleg Bykov ([email protected]) // Copyright (c) 2001 // // Modified by jingzhou Xu ////////////////////////////////////////////////////////////////////// #if !defined(AFX_PICTUREEX_H__0EFE5DE0_7B68_4DB7_8B34_5DC634948438__INCLUDED_) #define AFX_PICTUREEX_H__0EFE5DE0_7B68_4DB7_8B34_5DC634948438__INCLUDED_ #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 #include <vector> //#define GIF_TRACING // uncomment it if you want detailed TRACEs class CPictureEx : public CStatic { public: struct TFrame // structure that keeps a single frame info { IPicture *m_pPicture; // pointer to the interface used for drawing SIZE m_frameSize; SIZE m_frameOffset; UINT m_nDelay; // delay (in 1/100s of a second) UINT m_nDisposal; // disposal method }; #pragma pack(1) // turn byte alignment on enum GIFBlockTypes { BLOCK_UNKNOWN, BLOCK_APPEXT, BLOCK_COMMEXT, BLOCK_CONTROLEXT, BLOCK_PLAINTEXT, BLOCK_IMAGE, BLOCK_TRAILER }; enum ControlExtValues // graphic control extension packed field values { GCX_PACKED_DISPOSAL, // disposal method GCX_PACKED_USERINPUT, GCX_PACKED_TRANSPCOLOR }; enum LSDPackedValues // logical screen descriptor packed field values { LSD_PACKED_GLOBALCT, LSD_PACKED_CRESOLUTION, LSD_PACKED_SORT, LSD_PACKED_GLOBALCTSIZE }; enum IDPackedValues // image descriptor packed field values { ID_PACKED_LOCALCT, ID_PACKED_INTERLACE, ID_PACKED_SORT, ID_PACKED_LOCALCTSIZE }; struct TGIFHeader // GIF header { char m_cSignature[3]; // Signature - Identifies the GIF Data Stream // This field contains the fixed value 'GIF' char m_cVersion[3]; // Version number. May be one of the following: // "87a" or "89a" }; struct TGIFLSDescriptor // Logical Screen Descriptor { WORD m_wWidth; // 2 bytes. Logical screen width WORD m_wHeight; // 2 bytes. Logical screen height unsigned char m_cPacked; // packed field unsigned char m_cBkIndex; // 1 byte. Background color index unsigned char m_cPixelAspect; // 1 byte. Pixel aspect ratio inline int GetPackedValue(enum LSDPackedValues Value); }; struct TGIFAppExtension // application extension block { unsigned char m_cExtIntroducer; // extension introducer (0x21) unsigned char m_cExtLabel; // app. extension label (0xFF) unsigned char m_cBlockSize; // fixed value of 11 char m_cAppIdentifier[8]; // application identifier char m_cAppAuth[3]; // application authentication code }; struct TGIFControlExt // graphic control extension block { unsigned char m_cExtIntroducer; // extension introducer (0x21) unsigned char m_cControlLabel; // control extension label (0xF9) unsigned char m_cBlockSize; // fixed value of 4 unsigned char m_cPacked; // packed field WORD m_wDelayTime; // delay time unsigned char m_cTColorIndex; // transparent color index unsigned char m_cBlockTerm; // block terminator (0x00) public: inline int GetPackedValue(enum ControlExtValues Value); }; struct TGIFCommentExt // comment extension block { unsigned char m_cExtIntroducer; // extension introducer (0x21) unsigned char m_cCommentLabel; // comment extension label (0xFE) }; struct TGIFPlainTextExt // plain text extension block { unsigned char m_cExtIntroducer; // extension introducer (0x21) unsigned char m_cPlainTextLabel; // text extension label (0x01) unsigned char m_cBlockSize; // fixed value of 12 WORD m_wLeftPos; // text grid left position WORD m_wTopPos; // text grid top position WORD m_wGridWidth; // text grid width WORD m_wGridHeight; // text grid height unsigned char m_cCellWidth; // character cell width unsigned char m_cCellHeight; // character cell height unsigned char m_cFgColor; // text foreground color index unsigned char m_cBkColor; // text background color index }; struct TGIFImageDescriptor // image descriptor block { unsigned char m_cImageSeparator; // image separator byte (0x2C) WORD m_wLeftPos; // image left position WORD m_wTopPos; // image top position WORD m_wWidth; // image width WORD m_wHeight; // image height unsigned char m_cPacked; // packed field inline int GetPackedValue(enum IDPackedValues Value); }; #pragma pack() // turn byte alignment off public: CPictureEx(); virtual ~CPictureEx(); void Stop(); // stops animation void UnLoad(); // stops animation plus releases all resources BOOL IsGIF() const; BOOL IsAnimatedGIF() const; SIZE GetSize() const; int GetFrameCount() const; COLORREF GetBkColor() const; void SetBkColor(COLORREF clr); // draws the picture (starts an animation thread if needed) BOOL Draw(); // loads a picture from a file // i.e. Load(_T("mypic.gif")); BOOL Load(LPCTSTR szFileName); // loads a picture from a global memory block (allocated by GlobalAlloc) // Warning: this function DOES NOT free the global memory, pointed to by hGlobal BOOL Load(HGLOBAL hGlobal, DWORD dwSize); // loads a picture from a program resource // i.e. Load(MAKEINTRESOURCE(IDR_MYPIC),_T("GIFTYPE")); BOOL Load(LPCTSTR szResourceName,LPCTSTR szResourceType); protected: #ifdef GIF_TRACING void EnumGIFBlocks(); void WriteDataOnDisk(CString szFileName, HGLOBAL hData, DWORD dwSize); #endif // GIF_TRACING SIZE m_PictureSize; COLORREF m_clrBackground; UINT m_nDataSize; UINT m_nCurrOffset; UINT m_nGlobalCTSize; BOOL m_bIsGIF; BOOL m_bExitThread; BOOL m_bIsInitialized; HDC m_hMemDC; HBITMAP m_hBitmap; HBITMAP m_hOldBitmap; HANDLE m_hThread; HANDLE m_hExitEvent; IPicture * m_pPicture; TGIFHeader * m_pGIFHeader; unsigned char * m_pRawData; TGIFLSDescriptor * m_pGIFLSDescriptor; std::vector<TFrame> m_arrFrames; void ThreadAnimation(); static UINT WINAPI _ThreadAnimation(LPVOID pParam); int GetNextBlockLen() const; BOOL SkipNextBlock(); BOOL SkipNextGraphicBlock(); BOOL PrepareDC(int nWidth, int nHeight); void ResetDataPointer(); enum GIFBlockTypes GetNextBlock() const; UINT GetSubBlocksLen(UINT nStartingOffset) const; HGLOBAL GetNextGraphicBlock(UINT *pBlockLen, UINT *pDelay, SIZE *pBlockSize, SIZE *pBlockOffset, UINT *pDisposal); // Generated message map functions //{{AFX_MSG(CMyStatic) afx_msg void OnDestroy(); afx_msg void OnPaint(); //}}AFX_MSG DECLARE_MESSAGE_MAP() }; #endif // !defined(AFX_PICTUREEX_H__0EFE5DE0_7B68_4DB7_8B34_5DC634948438__INCLUDED_)

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值