700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > 预编译指令与宏定义

预编译指令与宏定义

时间:2018-04-27 13:37:13

相关推荐

预编译指令与宏定义

#if #elif [defined(), !defined()] #else #ifdef #ifndef #endif // 条件编译

/* 头文件防止多次被包含 */#ifndef ZLIB_H#define ZLIB_H#endif /* ZLIB_H *//* 用C方式来修饰函数与变量 */#ifdef __cplusplusextern "C" {#endifint add(int a, int b);int g_nVal = 0;#ifdef __cplusplus}#endif/* 条件嵌套 */#ifdef __STDC_VERSION__# ifndef STDC# define STDC# endif# if __STDC_VERSION__ >= 199901L# endif# if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus))# define STDC# endif#endif/* 日志输出 */#if defined( DEBUG ) && defined( _MSC_VER )# include <windows.h># define PRINT_LOG OutputDebugString#else# define PRINT_LOG printf#endif/* MFC中_AfxCopyString的实现*/inline LPOLESTR AFXAPI _AfxCopyString(LPCTSTR psz){if (psz == NULL)return NULL;int cch = lstrlen(psz) + 1;LPOLESTR pszCopy = NULL;if ((pszCopy = (LPOLESTR)CoTaskMemAlloc(cch * sizeof(OLECHAR))) != NULL){#ifdef _UNICODEwcscpy(pszCopy, psz);#elif !defined(OLE2ANSI)MultiByteToWideChar(CP_ACP, 0, psz, -1, pszCopy, cch);#elselstrcpy(pszCopy, psz);#endif}return pszCopy;}

#define #undef // 宏定义、宏取消

#define FAR#define _DEBUG#define MAX_PATH 260#define NULL ((void *)0)#define PASCAL __stdcall#define CALLBACK FAR PASCAL#define DEBUG_NEW new#define new DEBUG_NEW#define _PUC unsigned char *#define _CPUC const unsigned char *#define _PCchar *#define _CPC const char *#define _UIunsigned int#define MAX(a,b) (((a) > (b)) ? (a) : (b))#define TRACE ::AfxTrace#define TRACE0(sz) ::AfxTrace(_T("%s"), _T(sz))#define TRACE1(sz, p1)::AfxTrace(_T(sz), p1)#define TRACE2(sz, p1, p2)::AfxTrace(_T(sz), p1, p2)#define TRACE3(sz, p1, p2, p3) ::AfxTrace(_T(sz), p1, p2, p3)// 重新定义FALSE、TRUE、NULL#undef FALSE#undef TRUE#undef NULL#define FALSE 0#define TRUE 1#define NULL 0/* TCHAR.H */#ifdef _UNICODEtypedef wchar_tTCHAR;#define __T(x)L ## x#define _tmainwmain#define _tprintf wprintf#elsetypedef char TCHAR;#define __T(x)x#define _tmainmain#define _tprintf printf#endif#define _TEXT(x) __T(x)#define _T(x) __T(x)/* 使用OF宏来适配函数参数 */#ifndef OF# ifdef STDC# define OF(args) args# else# define OF(args) ()# endif#endifint add OF((int a, int b));/* 宏必须在一行写完,多行写时必须带上 \行连接符 *//* 注意##字符拼接符 */#define DECLARE_DYNAMIC(class_name) \public: \static const AFX_DATA CRuntimeClass class##class_name; \virtual CRuntimeClass* GetRuntimeClass() const;/* Debug时可使用THIS_FILE变量获得当前文件名*/#ifdef _DEBUG#undef THIS_FILEstatic char THIS_FILE[] = __FILE__;#endif

## # #@ // 特殊符号

/* ## 字符拼接符 */#define Conn(x,y) x ## yint n = Conn(123,456); //n = 123456;char* str = Conn("abc","def"); //str = "abcdef";/* # 加双引号 */#define ToString(x) #x#define PrintAge(age) printf("I am " #age " years old.\n") // 注:字符串是可以用空格分开写的,编译器会将其合成一个字符串;如:printf("Hello " "World" "!")等价于printf("Hello World!")char* str = ToString(12.345); //str= "12.345"PrintAge(20); // 输出 I am 20 years old./* #@ 加单引号 */#define ToChar(x) #@xchar ch = ToChar(a); //ch='a'

#include #include_next【GNU的一个扩展,gcc下可使用】 // 文件包含

#include <stdio.h> // 只搜索系统目录#include "stdafx.h" // 先搜索工程当前目录,再搜索系统目录#include "../zlib/zconf.h" // 以当前文件作为参考来计算// #include_next为GNU的一个扩展,gcc下可使用// #include_next <xx.h> 包含在搜索路径列表中第2次找到的xx.h// 例如:搜索路径顺序为:/usr/local/include,/usr/include// 如果这两个目录下都有signal.h文件,将引用/usr/include中的那个#include_next <signal.h>// 另外#include_next不区分""与<>,都是先搜索工程当前目录,再搜索系统目录

#line 指示下一行的行号,及当前所在的文件;该命令会修改__FILE__、__LINE__的值

该命令是提供给编译器使用的,程序员最好不要使用该命令,否则会导致调试异常(如:断点打不上等)

#line 100 "myFile.cpp"printf("File: %s, Line: %d, Function: %s\n", __FILE__, __LINE__ ,__FUNCTION__); // 输出File: f:\vstest\vstest\myfile.cpp, Line: 101, Function: wmain

#pragma

#pragma once // 防止头文件重复包含【vc编译器版本:_MSC_VER > 1000时才支持#pragma once】#pragma message ("发布版本请去掉测试代码") // 编译时打印自定义信息#pragma warning(disable: 4102 4235) // 不提示C4102、C4235的warning#pragma warning(once:4385) // C4385警告仅报告一次 #pragma warning(error:164) // C164警告信息视为错误#pragma warning(default: 4310) // 将C4310的警告行为到默认状态#pragma warning(disable:4507 34; once:4385; error:164)#pragma warning(push) //保存现有警告状态 #pragma warning(push, 3) //保存现有警告状态,并且把warning level设为3#pragma warning(pop) //弹出栈顶的一个警告信息,这对导致push和pop之间所作的一切改动取消掉#pragma comment(lib, "../zlib/zlib.lib") // 链入zlib.lib导出库// 目录结构如下:+-- testStdafx.h|- Debug+-- testLib.lib#pragma comment(lib, __FILE__ "\\..\\" "Debug\\" "testLib.lib") // 若当前文件为testStdafx.h,在testStdafx.h中包含自己的lib文件,可以避免外部工程手动包含test.lib// 外部工程只需要#include "testStdafx.h"即可,如果多个工程使用testLib.lib,这个做法非常方便// 后面路径分段个数没有限制,理论上任意多个都行/*#pragma data_seg指定函数存放在*.obj文件中的数据段,默认的代码段是.data*/int i = 0; // 存放在"data"段#pragma data_seg(".my_data1")int j = 1; // 存放在"my_data1"段#pragma data_seg(push, stack1, ".my_data2") int k = 2; // 存放在"my_data2"段#pragma data_seg(pop, stack1) // pop stack1 off the stackint m = 3; // 存放在"my_data1"段#pragma data_seg()int n = 4; // 存放在"data"段/*#pragma code_seg指定函数存放在*.obj文件中的代码段,默认的代码段是.text*/void func1() {} // 存放在text段#pragma code_seg(".my_data1")void func2() {} // 存放在my_data1段#pragma code_seg(push, r1, ".my_data2")void func3() {} // 存放在my_data2段#pragma code_seg(pop, r1)void func4() {} // 存放在my_data1段#pragma code_seg()void func5() {} // 存放在text段/* 除了data_seg和code_seg之外,还有bss_seg与const_seg *//* bss_seg与const_seg的使用与data_seg、code_seg一致*///shareddata 一般用于dll中;共享数据必须初始化,否则会放到.BSS段中#pragma data_seg("shareddata")int nTotalNum = 0; //nTotalNum可以被多个进程共享#pragma data_seg()/* #pragma comment(linker,...)主要用来设置链接参数 *//* 常见的链接参数详见: *//* /kekec/archive//04/21/3007277.html中的Link.exe段的说明 */// 将flag_data数据段设置为可读、可写、可共享#pragma comment(linker,"/SECTION:flag_data,RWS")// 导出extern "C" fnSub函数#pragma comment (linker, "/EXPORT:_fnSub")// 导出extern "C" fnAdd函数,并将符号名修改为myfnAdd,同时将导出序号设为1#pragma comment (linker, "/EXPORT:myfnAdd=_fnAdd,@1")// 强制包含名为__mySymbol的符号;// 若要指定多个符号,请在符号名称之间键入逗号、分号或空格#pragma comment(linker, "/include:__mySymbol")/* 区别:源码的inline在编译器进行预处理的时候就展开了,*//* 而#Pragma intrinsic却是以二进制的方式inline进去的 */// 使用内联版本的memset及strlen#pragma intrinsic(memset, strlen)/* 使用回函数调用的strlen */#pragma function(strlen)/* 对于不同文件中的全局对象、变量,它们的构造函数调用顺序是未定义的,取决于具体的编译器,这就可能带来一些问题 *//* compiler、lib、user,初始化优先次序依次降低,但都先于普通的全局变量构造*//* 对于必须优先被初始化的对象或变量应使用这3个指令 *//* 一个源文件只能出现一次init_seg 指令 */#pragma init_seg(compiler)#pragma init_seg(lib)#pragma init_seg(user)#pragma init_seg("user_defined_segment_name") // 用户自定义名称// 内存对齐// 详见:/kekec/archive//10/31/2748955.html#pragma pack(push, 4)#pragma pack(pop)#pragma optimize("", off) // 关闭代码编译优化#pragma optimize("", on) // 开启代码编译优化#pragma inline_recursion(on) // 开启内联递归#pragma inline_recursion(off) // 关闭内联递归// 函数堆栈深度超过指定深度,就不进行函数内联#pragma inline_depth(0) // 不进行任何内联#pragma inline_depth(10) // 深度超过10层,不进行函数内联#pragma inline_depth() // 缺省深度值为254// myheader.h关闭最小重新生成【见/Gm编译选项】/* myheader.h起始处 */#pragma component(minrebuild, off)/* myheader.h */#pragma component(minrebuild, on)/* myheader.h结束处 */

#error // c编译器error命令

#ifndef __cplusplus#error MFC requires C++ compilation (use a .cpp suffix)#endifextern "C"{#error "printf error!"};

__VA_ARGS__ 【变参】 新的C99规范中增加的,gcc及vs版本以上的ms编译器支持该宏

/* vs测试 */#define debug1(...) printf(__VA_ARGS__)#define debug2(fmt, ...) printf(fmt, __VA_ARGS__)#define debug3(fmt, ...) printf(fmt, ## __VA_ARGS__)int a = 10;const char* chs = "Hello";debug1("%d %s\n", a, chs); // printf("%d %s\n", a, chs);debug2("%d %s\n", a, chs); // printf("%d %s\n", a, chs);debug3("%d %s\n", a, chs); // printf("%d %s\n",a, chs); a前会少一个空格/* 安全调用对象的方法 */#define SafeCallFunc(ptr, retType, func, ...) ( (ptr!=NULL)?(ptr->func(__VA_ARGS__)):(retType(0)) )/* 安全获取对象的成员变量 */#define SafeGetValue(ptr, val, valType) ( (ptr!=NULL)?(ptr->val):(valType(0)) )

注:__VA_ARGS__前加上##的作用在于,当可变参数的个数为0时,将##前面多余的逗号去掉,否则会编译不过(vs不加##,也可以编译过)

__FILE__、__LINE__、__FUNCTION__、__DATE__、__TIME__、__TIMESTAMP__

// File: f:\vsconsole1\vsconsole1\vsconsole1.cpp, Line: 9, Function: wmain// vc6不支持__FUNCTION__宏printf("File: %s, Line: %d, Function: %s\n",__FILE__,__LINE__,__FUNCTION__);// Date: Sep 19 Time: 22:38:51 TimeStamp: Thu Sep 19 22:38:50 printf("Date: %s Time: %s TimeStamp: %s\n",__DATE__,__TIME__, __TIMESTAMP__);

注:__DATE__、__TIME__、__TIMESTAMP__会被替换成该源文件编译成obj文件时的日期、时间、和unix时间戳

__STDC__、__STDC_VERSION__、__cplusplus

__STDC__ // 当前编译器符合c标准,则该宏的值为1__STDC_VERSION__ // 当前编译器符合C89, 该宏的值为199409L, 符合C99, 该宏的值为199901L__cplusplus // 当前编译器符合c++标准,则该宏值为编译器版本号// C++ pre-C++98: __cplusplus is 1// C++98: __cplusplus is 199711L// C++98 + TR1: This reads as C++98 and there is no way to check that I know of// C++11: __cplusplus is 03L// C++14: __cplusplus is 02L

_MSC_VER

_MSC_VER = 1800 // MS VC++ 12.0_MSC_VER = 1700 // MS VC++ 11.0_MSC_VER = 1600 // MS VC++ 10.0 _MSC_VER = 1500 // MS VC++ 9.0 _MSC_VER = 1400 // MS VC++ 8.0 _MSC_VER = 1310 // MS VC++ 7.1 _MSC_VER = 1300 // MS VC++ 7.0 _MSC_VER = 1200 // MS VC++ 6.0 _MSC_VER = 1100 // MS VC++ 5.0

参考:/wiki/Microsoft_Visual_Studio

WINVER

win32具有良好的向下兼容性,低版本的win32程序可以在后续高版本的windows系统上正确运行

随着windows版本的升级,更多Windows API被加入,为了能在程序中使用这些新增的API函数,可以将WINVER宏设定到更高的版本,保证程序能编译链接到windows SDK中的这些API;

但与此同时,也带来了新的问题,意味着你的程序只能在更高版本的windows上运行

How to modify WINVER Using the Windows Headers

参考:/wiki/List_of_Microsoft_Windows_versions

/wiki/Comparison_of_Microsoft_Windows_versions

编译时打印出宏的内容

//测试宏#define PI 3.1415926#define MAX(a,b) (a)>(b) ? (a) :(b)//首先定义两个辅助宏#define PRINT_MACRO_HELPER(x) #x#define PRINT_MACRO(x) #x"="PRINT_MACRO_HELPER(x)//编译时打印出宏的内容#pragma message(PRINT_MACRO(PI)) // PI=3.1415926#pragma message(PRINT_MACRO(PI2)) // PI2=PI2 注:PI2没定义#pragma message(PRINT_MACRO(MAX(a,b)))// MAX(a,b)=(a)>(b) ? (a) :(b)#pragma message(PRINT_MACRO(MAX(x,y))) // MAX(x,y)=(x)>(y) ? (x) :(y)

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。