C++预编译

#if !defined(AFX__H__180E70AF_83B5_4CAD_9AF7_950350AB63C7__INCLUDED_)

 #define AFX__H__180E70AF_83B5_4CAD_9AF7_950350AB63C7__INCLUDED_

...

#endif   //!defined(AFX__H__180E70AF_83B5_4CAD_9AF7_950350AB63C7__INCLUDED_)

      这是一中常见的防止头文件(.h文件)被重复包含的格式,这是vc6及更低版本的防止该头文件被重复include之后被重复编译的一贯做法。在vs2003及更高版本,可以用 #pragma once 来替代类似的功能。


#ifndef  XXX_H__XX

#define XXX_H__XX

#endif

就是说如果XXX_H__XX没有定义过,证明这个文件没有被包含过,因为XXX_H__XX是一个比较唯一的宏名(你这个那么长就是保证唯一性),如果包含了,整个这个#if  #endif之间的代码就不被包含了

 

#if  _MSC_VER > 1000 //这个貌似是检查编译器版本的

#pragma once //这个和上面那个#if #endif那个性质是一样的,防重复包含

#endif // _MSC_VER > 1000

 

#ifndef __AFXWIN_H__ //如果这个宏没定义

#error include 'stdafx.h' before including this file for PCH //编译器在编译代码时输出一个错误

#endif

#include "resource.h"

 

 

对于一个大程序而言,我们可能要定义很多常量( 不管是放在源文件(.cpp)还是头文件(.h) ),那么我们有时考虑定义某个常量时,我们就必须返回检查原来此常量是否定义,但这样做很麻烦.if defined宏正是为这种情况提供了解决方案.举个例子,如下:

#define ....
#define ....
........
........
#define a 100
.......
此时,我们要检查a是否定义(假设我们已经记不着这点了),或者我们要给a一个不同的值,就加入如下句子
#if defined a
#undef a
#define a 200
#endif
上述语句检验a是否被定义,如果被定义,则用#undef语句解除定义,并重新定义a为200

同样,检验a是否定义:
#ifndef a //如果a没有被定义
#define a 100
#endif

以上所用的宏中:#undef为解除定义,#ifndef是if not defined的缩写,即如果没有定义。

这就是#if defined 的唯一作用!
 
#define _WIN32_WINNT 0x0500 在程序前面定义一下,_WIN32_WINNT用来让编译器知道你的操作系统是哪个版本的,因为有些API函数,早期的Windows版本不支持,当值大于等于0x0500表示是Windows 2000或以上版本。

 

 

 

// Game.h: interface for the CGame class.
//
//

#if !defined(AFX_GAME_H__18287D61_DB36_11D3_B12A_F67D0FBE8D25__INCLUDED_)
#define AFX_GAME_H__18287D61_DB36_11D3_B12A_F67D0FBE8D25__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include <ddraw.h>
#include "Plane.h"
#include "Sprite.h"
#include "Input.h"
#include "Sound.h"

#define NUM_BITMAPS		15
#define NUM_EXPLODES	20
#define NUM_ENEMYS		6


enum GAMESTATE
{
	GS_SPLASH,
	GS_ACTIVE,
	GS_WIN,
	GS_OVER,
};


class CGame  
{
public:
	CGame();
	virtual ~CGame();

	BOOL	Initialize( HINSTANCE hInst );
	BOOL	InitApplication();
	BOOL	DDInit();
	void	DDTerm();
	void	ResetPlayer( CPlayer& player );
	BOOL	InitLevel();
	BOOL	InitGame();
	BOOL	ResetGame();
	void	CleanUpGame();
	void	DDClear( RECT* prc, DWORD dwFillColor );
	void	FlipScreen();
	void	ProcessInput();
	void	UpdateFrame();
	int		Run();
	void	Explode( CSprite& sprite, BOOL bExplode=FALSE );
	void	PlayerBeenHit( CPlayer& player );
	BOOL	BoreBonus();
	BOOL	BoreEnemy();
	void	EatBonus( CPlayer& player );
	void	EatBonus( CEnemy& enemy );	
	void	GameOver();
	BOOL	LoadBitmaps();
	void	RestoreSurfaces();
	void	OutputText( int x, int y, LPCTSTR string );

	void	DoSplash();
	void	DrawWorld();
	void	BltNumber( int x, int y, int n );

	LPDIRECTDRAWSURFACE DDLoadBitmap( LPCSTR szBitmap, int dx=0, int dy=0 );
	LPDIRECTDRAWSURFACE DDCreateSurface( int width, int height );
	LRESULT MsgProc( HWND hWnd, UINT uMsg, WPARAM, LPARAM );

private:
	HINSTANCE	m_hInst;
	HWND		m_hWnd;
	BOOL		m_bActive;
	BOOL		m_bShowStats;
	BOOL		m_bFullScreen;
	BOOL		m_bSingle;
	RECT		m_rcWindow;
	DWORD		m_dwFillColor;

	LPDIRECTDRAW			m_pDD;
	LPDIRECTDRAWSURFACE		m_pddsFrontBuffer;
	LPDIRECTDRAWSURFACE		m_pddsBackBuffer;
	LPDIRECTDRAWSURFACE		m_pBmpList[NUM_BITMAPS];

	CDirectInput	m_DirectInput;
	CDirectSound	m_DirectSound;

	CPlane		m_plane;
	CPlayer		m_player[2];
	CEnemy		m_enemy[NUM_ENEMYS];
	int			m_nMaxEnemys;
	CExplode	m_explode[NUM_EXPLODES];
	CBonus		m_bonus;

	GAMESTATE	m_gameState;
	DWORD		m_lastTime;
	int			m_nLevel;
	int			m_nEnemysLeft;
	int			m_nEnemys;
	BOOL		m_bEnemyLocked;
	DWORD		m_lockTime;
};


HRESULT DDCopyBitmap( LPDIRECTDRAWSURFACE, HBITMAP hbm, int x, int y, int dx, int dy);
HRESULT DDReLoadBitmap(LPDIRECTDRAWSURFACE, LPCSTR szBitmap);
HRESULT DDSetColorKey(LPDIRECTDRAWSURFACE, COLORREF);
DWORD DDColorMatch(LPDIRECTDRAWSURFACE, COLORREF);

#endif // !defined(AFX_GAME_H__18287D61_DB36_11D3_B12A_F67D0FBE8D25__INCLUDED_)

 

 

 

在编写程序的时候,我们经常要用到#pragma指令来设定编译器的状态或者是指示编译器完成一些特定的动作。

一   message参数。  

它能够在编译信息输出窗口中输出相应的信息,这对于源代码信息的控制是非常重要的。

其使用方法为:        
    #pragma   message( "消息文本")    

当编译器遇到这条指令时就在编译输出窗口中将消息文本打印出来。    
当我们在程序中定义了许多宏来控制源代码版本的时候,我们自己有可能都会忘记有没有正确的设置这些宏,此时我们可以用这条指令在编译的时候就进行检查。假设我们希望判断自己有没有在源代码的什么地方定义了_X86这个宏可以用下面的方法    
    #ifdef   _X86    
    #pragma   message( "_X86   macro   activated! ")    
    #endif    
当我们定义了_X86这个宏以后,应用程序在编译时就会在编译输出窗口里显示 "_X86   macro   activated! "。我们就不会因为不记得自己定义的一些特定的宏而抓耳挠腮了。    

       
二   另一个使用得比较多的#pragma参数是code_seg。

格式如:
    #pragma   code_seg([[{push|pop},][identifier,]]["segment-name"[,"segment-class "])  

该指令用来指定函数在.obj文件中存放的节,观察obj文件可以使用VC自带的dumpbin命令行程序,函数在.obj文件中默认的存放节为.text节。如果code_seg没有带参数的话,则函数存放在.text节中。

    push                         (可选参数)将一个记录放到内部编译器的堆栈中,可选参数可以为一个标识符或者节名;
    pop                           (可选参数)将一个记录从堆栈顶端弹出,该记录可以为一个标识符或者节名;
    identifier             (可选参数)当使用push指令时,为压入堆栈的记录指派的一个标识符,当该标识符被删除的时候和其相关的堆栈中的记录                                                         将被弹出堆栈;  
    segment-name     (可选参数)表示函数存放的节名。

例如:
//默认情况下,函数被存放在.text节中
void   func1()  {                                     //   stored   in   .text
}

//将函数存放在.my_data1节中
#pragma   code_seg( ".my_data1 ")
void   func2()   {                                     //   stored   in   my_data1
}

//r1为标识符,将函数放入.my_data2节中
#pragma   code_seg(push,   r1,   ".my_data2 ")
void   func3()   {                                     //   stored   in   my_data2
}

int   main()   {
}


三   #pragma   once(比较常用)    

这是一个比较常用的指令,只要在头文件的最开始加入这条指令就能够保证头文件被编译一次
       

四   #pragma   hdrstop表示预编译头文件到此为止,后面的头文件不进行预编译

BCB可以预编译头文件以加快链接的速度,但如果所有头文件都进行预编译又可能占太多磁盘空间,所以使用这个选项排除一些头文件。有时单元之间有依赖关系,比如单元A依赖单元B,所以单元B要先于单元A编译。你可以用#pragma   startup指定编译优先级,如果使用了#pragma   package(smart_init),BCB就会根据优先级的大小先后编译。      


五   #pragma   warning指令

该指令允许有选择性的修改编译器的警告消息的行为,指令格式如下:
    #pragma   warning(warning-specifier : warning-number-list [; warning-specifier : warning-number-list...]
    #pragma   warning(push[,n])
    #pragma   warning(pop)

主要用到的警告表示有如下几个:

    once:   只显示一次(警告/错误等)消息
    default:重置编译器的警告行为到默认状态
    1,2,3,4:四个警告级别
    disable:禁止指定的警告信息
    error:   将指定的警告信息作为错误报告

如果大家对上面的解释不是很理解,可以参考一下下面的例子及说明
 
    #pragma   warning(   disable   :   4507   34;   once   :   4385;   error   :   164   )    
等价于:    
    #pragma   warning(disable:4507   34)     //   不显示4507和34号警告信息    
    #pragma   warning(once:4385)                 //   4385号警告信息仅报告一次    
    #pragma   warning(error:164)                 //   把164号警告信息作为一个错误。    
同时这个pragma   warning   也支持如下格式:    
    #pragma   warning(   push   [   ,n   ]   )    
    #pragma   warning(   pop   )    
这里n代表一个警告等级(1---4)。    
    #pragma   warning(   push   )保存所有警告信息的现有的警告状态。    
    #pragma   warning(   push,   n)保存所有警告信息的现有的警告状态,并且把全局警告等级设定为n。      
    #pragma   warning(   pop   )向栈中弹出最后一个警告信息,在入栈和出栈之间所作的一切改动取消。
例如:    
    #pragma   warning(   push   )    
    #pragma   warning(   disable   :   4705   )    
    #pragma   warning(   disable   :   4706   )    
    #pragma   warning(   disable   :   4707   )    
    #pragma   warning(   pop   )

在这段代码的最后,重新保存所有的警告信息(包括4705,4706和4707)

在使用标准C++进行编程的时候经常会得到很多的警告信息,而这些警告信息都是不必要的提示,所以我们可以使用#pragma   warning(disable:4786)来禁止该类型的警告。在vc中使用ADO的时候也会得到不必要的警告信息,这个时候我们可以通过#pragma   warning(disable:4146)来消除该类型的警告信息。


六   pragma   comment(...)
该指令的格式为:    
    #pragma   comment(   "comment-type "   [,   commentstring]   )   该指令将一个注释记录放入一个对象文件或可执行文件中,
    comment-type(注释类型):可以指定为五种预定义的标识符的其中一种,五种预定义的标识符为: 
    compiler:将编译器的版本号和名称放入目标文件中,本条注释记录将被编译器忽略。如果你为该记录类型提供了commentstring参数,编译器将会产生一个警告。

    例如:#pragma   comment(compiler)
        exestr:将commentstring参数放入目标文件中,在链接的时候这个字符串将被放入到可执行文件中,当操作系统加载可执行文件的时候,该参数字符串不会被加载到内存中。但是,该字符串可以被dumpbin之类的程序查找出并打印出来,你可以用这个标识符将版本号码之类的信息嵌入到可执行文件中!
        lib:这是一个非常常用的关键字,用来将一个库文件链接到目标文件中常用的lib关键字,可以帮我们连入一个库文件。     
    例如: #pragma   comment(lib,   "user32.lib ")   该指令用来将user32.lib库文件加入到本工程中。 
        linker:将一个链接选项放入目标文件中,你可以使用这个指令来代替由命令行传入的或者在开发环境中设置的链接选项,你可以指定/include选项来强制包含某个对象,

    例如: #pragma   comment(linker,   "/include:__mySymbol ") 
        你可以在程序中设置下列链接选项 
                                                    /DEFAULTLIB  
                                                    /EXPORT  
                                                    /INCLUDE  
                                                    /MERGE  
                                                    /SECTION   
        这些选项在这里就不一一说明了,详细信息请看msdn!
        user: 将一般的注释信息放入目标文件中commentstring参数包含注释的文本信息,这个注释记录将被链接器忽略
                            例如: #pragma   comment(user, "Compiled  on"   __DATE__  "at"  __TIME_)

 

七   #pragma deprecated("strncpy")表示‍strncpy这个函数不安全,如果非要调用则会得到一个warning 

 

八    #define   chSTR2(x)   #x
  这个是串化,chSTR2(1 + 1 == 2)   替换成   "1 + 1 == 2"


 

已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页