VC++編譯說明


1編譯步驟    1

2編譯源文件    2

2.1 編譯器    2

2.2 包含頭文件    3

2.3 重復包含    6

2.4 預編譯頭文件    7

2.4.1 創建    7

2.4.2 使用    8

2.4.3 說明    9

3編譯資源    10

3.1 編譯    10

3.1.1 輸出文件    10

3.1.2 語言    11

3.2 include語句    12

3.3 引用文件    13

4連接    14

5其它    17

5.1 編譯目錄    17

5.2 編譯事件    18

5.3 自定義編譯    19

5.4 預定義宏    22

5.4.1 ANSI C 預定義宏    22

5.4.2 微軟C++預定義宏    23

5.4.3 應用實例    28

5.5 預處理器操作符    28

5.5.1 #    28

5.5.2 #@    28

5.5.3 ##    28

5.5.4 defined    29

 

1編譯步驟

使用Visual C++ 6.0新建一個MFC程序,然后編譯。IDE(集成開發環境)下,可以看到編譯信息:

1.1 VC++6.0編譯信息

可見其編譯的基本步驟為:

1、刪除項目的臨時文件和輸出文件;

2、編譯資源,即編譯rc文件,生成res文件;

3、預編譯頭文件,生成pch文件;

4、編譯各個源文件(*.c*.cpp*.cxx),生成obj文件;

5、鏈接。具體的就是將objres文件合成為一個exe文件,中間可能還需要一些Lib文件。

注意:EVC3.0EVC4.0的編譯步驟與VC++6.0完全一致。VC++6.0之后的版本,其編譯步驟發生了變化。第2步的編譯資源被移至第4步之后。

從上面的編譯步驟可以看到,編譯時並沒有編譯頭文件(*.h)。這樣是否就意味着不需要頭文件了?答案當然是否定的。事實上在編譯源文件時,預編譯器首先處理#include指令,它會將頭文件包含至源文件后再進行編譯。編譯器是以這種方式使用頭文件的,認識到這一點對於理解C/C++編譯至關重要。

2編譯源文件

VC++6.0里編譯就是調用C:\Program Files\Microsoft Visual Studio\VC98\Bin\cl.exe將源文件(*.c*.cpp*.cxx)編譯為obj文件。

2.1 編譯器

假定1.cpp里有如下代碼:

int a = 0;

++a;

int b = a + 1;

顯然編譯它是沒問題的,但是把1.cpp改名為1.c,再次編譯就會出問題。為什么?原因很簡單:源文件的擴展名為c時,編譯器按C語言的語法進行編譯,生成C代碼;源文件的擴展名為cppcxx時,編譯器按C++語言的語法進行編譯,生成C++代碼。CC++語法還是有一定差別的。

大家都知道C++支持函數重載,如下面兩個函數在C++里是允許的:

int fun();

int fun(int a); 

但在C語言里是不允許的。為什么呢?因為C語言編譯fun時不會將其更名,一個obj文件里是不能有兩個同名函數的。C++語言就不同了,會將這兩個函數自動更名。VC++6.0里將fun()更名為?fun@@YAHXZ,將fun(int a)更名為?fun@@YAHH@Z,程序員眼里的一個函數fun在編譯器眼里仍是兩個。

這樣就引來一個問題:如果一個函數funA.c文件里,而程序在.cpp里調用了funA函數會出現什么情況?答案是無法調用:因為funAobj里的名字就是funA,但cpp要連接的funA已經被更名了。為了在cpp里調用c函數,函數聲明時需要使用extern "C"語句。如下面代碼。

extern "C" int fun();

extern "C"

{

int funcA();

int funcB();

} 

CC++混合編程的時候一定要注意這個問題。

2.2 包含頭文件

編譯源文件時,若遇到 #include "A.h" 語句,則編譯器對頭文件的搜索順序如下:

1#include語句所在文件的目錄

如:C:\VC\1.c 里有 #include "A.h",則編譯器會在1.c所在目錄查找A.h,即在C:\VC下查找A.h

如:C:\VC\1.c 里有 #include "../B.h",則編譯器會在1.c所在目錄查找../B.h,就是查找C:\VC\..\B.h,即C:\B.h。這里的..表示相對路徑,即上一級目錄。#include "../B.h"里的斜杠/可以換成反斜杠\,不過因為在雙引號里\表示轉義字符,所以需要兩個反斜杠,即:#include "..\\B.h"。以一個斜杠代替兩個反斜杠完全是為了簡化;

說明:相對路徑可通過vcHelper程序獲取,這樣較為方便。

2、上一級包含文件所在目錄

如:C:\VC\1.c 里有 #include "A.h"。編譯器在D:\Test目錄下找到了A.h。這個A.h里又有#include "B.h",顯然編譯器會首先在A.h所在目錄D:\Test下查找B.h,如果找不到則會在C:\VC\1.c所在目錄繼續查找。

3Additional include directories 所列目錄下依次進行查找

Additional include directories的設置僅對本項目有效,具體請參考圖2.1或圖2.2VC++6.0的多個路徑之間請以逗號分隔。路徑可以使用絕對路徑也可以使用相對路徑。如:C:/VC,../Share,./Inc表示了三個目錄:

C:\VC        絕對路徑

..\Share        相對於項目文件(dspvcpvcproj)的相對路徑

.\Inc        相對於項目文件(dspvcpvcproj)的相對路徑

搜索頭文件時,先搜索C:\VC目錄,再搜索..\Share目錄,最后搜索.\Inc目錄。

2.1 VC++6.0 Additional include directories

2.2 VC++7.0 Additional include directories

4、在Standard Include Paths里依次進行查找

Standard Include Paths的設置對所有VC++項目都有效。

VC++6.0下,單擊【Tools】菜單下的【Option】菜單項,然后進入Directories頁面,如下圖所示。

2.3 VC++6.0 Standard Include Paths

VC++7.0下,單擊【Tools】菜單下的【Option】菜單項。顯示界面如下圖所示。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

2.4 VC++7.0 Standard Include Paths

以上討論的是#include ""語句,如果是 #include <>,則對頭文件的查找順序將是上面的第 3、4步。

建議:

1、如果是自己寫的頭文件,請使用#include ""語句,並使用相對路徑;

2、如果是系統的頭文件,如:stdio.h,請使用#include <>語句。

2.3 重復包含

假如1.cpp里包含了頭文件A.hB.h,這兩個頭文件又都包含了C.h。顯然編譯1.cpp時,C.h將被包含兩次。C.h里的結構、類定義也會出現兩次,編譯器會認為這些結構、類被重復定義了,從而導致編譯失敗。

解決辦法有兩個

1、增加#ifndef ... #define ... #endif

如:在C.h里增加如下代碼:

//C.h

#ifndef __C_H__

#define __C_H__

//以下是C.h的文件內容

... ... ...

//最后別忘了#endif

#endif //__C_H__ 

編譯器編譯1.cpp,第二次包含C.h的時候,因為__C_H__已經被定義了,因此會舍棄第二次包含的內容。

該方法要保證每個頭文件里的__C_H__都不相同,否則會導致某兩個頭文件不能同時被包含。

2、增加#pragma once語句

這個方法比較簡單,直接在C.h里增加#pragma once即可。美中不足的是:並不是所有的編譯器都支持這條指令。所以,采用其它C/C++編譯器的時候要注意這一點。

2.4 預編譯頭文件

假如有多個源文件都包含了windows.h文件。這個頭文件非常大,每次編譯都比較耗時。有幾個源文件包含了它,它就要被編譯幾次。顯然這樣的編譯效率是相當低的。能不能只編譯一次這樣的頭文件?答案是肯定,那就是使用預編譯頭文件。即在編譯源文件之前,先把windows.h編譯出來生成pch文件。在編譯源文件的時候,編譯器遇到windows.h時將不再編譯,而是直接使用pch文件。這個pch就是預編譯頭文件。

2.4.1 創建

正如前面所說的,編譯器是不會直接編譯頭文件的。因此要預編譯頭文件,需要指定一個源文件來完成編譯並生成pch文件。這里假定要預編譯windows.h。請創建一個源文件,如:pch.cpp。其內容很簡單,就是#include <windows.h>。然后設置pch.cpp的屬性,使其創建pch文件。VC++6.0的設置界面如下:

2.5 VC++6.0創建預編譯頭文件設置

VC++7.0Solution Explorer里,右鍵單擊pch.cpp,然后單擊【Properties】菜單項,設置界面如下圖所示

2.6 VC++7.0創建預編譯頭文件設置

2.4.2 使用

創建PCH文件后,需要設置其它的源文件使用它。

VC++6.0的設置界面如下。

2.7 VC++6.0使用預編譯頭文件設置

VC++7.0Solution Explorer里,選擇要使用預編譯頭文件的源文件,然后右鍵單擊某一選中文件,或直接右鍵單擊項目然后單擊【Properties】菜單項,設置界面如下圖所示。注意下圖里的my.pch要和圖2.6的保持一致,即:創建什么pch文件就使用什么pch文件。

2.8 VC++7.0使用預編譯頭文件設置

設置多個源文件的屬性與設置項目屬性的區別:項目就好像國家,源文件就好像各個省。國家出台了政策后,各個省要遵循;但是各個省可以根據自己的情況對政策進行修改。一個源文件的某個屬性沒有進行設置,則它使用項目的該屬性。項目的屬性改變后,這個源文件的屬性也隨之改變。但是如果單獨對這個源文件的屬性進行了設置,則項目屬性的改變對它沒有影響。

2.4.3 說明

需要說明以下幾點:

1VC++7.0項目里可以使用多個預編譯頭文件;VC++6.0項目使用多個預編譯頭文件好像比較困難;

2、創建MFC程序后,預編譯頭文件設置已經完成,一般無需再設置;

3、一個源文件一旦使用了預編譯頭文件A.h,則該源文件的第一行一定要包含該頭文件。換句話說#include "A.h"之前的代碼將被忽略;

4、編譯預編譯頭文件出錯后,很難調試。因為不知道編譯到哪一行出錯了?解決方法就是使用#error#pragma message跟蹤編譯進度,精確定位編譯出錯的位置。

3編譯資源

Windows程序需要資源,如:圖標、光標、對話框……VC++6.0里編譯資源就是調用C:\Program Files\Microsoft Visual Studio\COMMON\MSDev98\Bin\rc.exe將資源文件(*.rc)編譯為res文件。連接程序負責將res文件嵌入exe文件。

3.1 編譯

使用記事本創建資源文件1.rc,其內容如下所示。只有一個 ID 100 的字符串。注意:1.rc的編碼必須為ANSI

STRINGTABLE DISCARDABLE

{

100 "This is a string"

}

DOS命令窗口,執行如下命令

"C:\Program Files\Microsoft Visual Studio\COMMON\MSDev98\Bin\rc.exe" C:\1.rc

rc.exe將編譯1.rc,並生成1.res。可以使用VC++6.0打開1.res,查看資源內容。

3.1.1 輸出文件

默認情況下,1.res1.rc在同一目錄。可以通過/fo命令開關更改輸出文件,如下命令將更改輸出文件為D:\t.res

"C:\Program Files\Microsoft Visual Studio\COMMON\MSDev98\Bin\rc.exe" /fo"D:\t.res" C:\1.rc

在集成開發環境下,Resource file name 對應的就是/fo命令開關。集成開發環境編譯時,會將dspvcproj文件所在目錄設置為當前目錄,所以如果Resource file name不是絕對路徑,那么它就是相對dsp文件目錄的相對路徑。

3.1 VC++6.0資源設置

 

 

 

 

 

 

 

 

3.2 VC++7.0資源設置

3.1.2 語言

1.rc文件修改成如下內容:

STRINGTABLE DISCARDABLE

{

100 "這是一個字符串"

}

使用VC++6.0打開編譯生成的res文件,會發現字符串是亂碼。因為rc.exe默認使用的語言是美國英語,語言ID0x409。需要將語言ID更改為簡體中文的0x804。具體命令如下:

"C:\Program Files\Microsoft Visual Studio\COMMON\MSDev98\Bin\rc.exe" /fo"D:\t.res" /l804 C:\1.rc

命令開關/l804相當於在1.rc的第一行插入如下語句:

LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED

即明確指定語言為簡體中文。

如果1.rc的第一行為 LANGUAGE 9,1。即已經指定語言為美國英語,則命令開關/l804是不起任何作用的。

在集成開發環境下,可以通過修改"Language"或"Culture"修改/l命令開關。

3.2 include語句

假定資源文件1.rc里有語句#include "1.rc2",而1.rc2里又有語句#include "2.rc2"。按如下命令進行編譯:

3.3 編譯資源

則查找2.rc2的順序如下:

1、包含它的文件(1.rc2)所在目錄;

21.rc21.rc包含,所以如果上一步未找到,繼續在1.rc所在目錄查找;

3、在當前目錄查找。上圖中,當前目錄就是C:\User\yhf

4、由命令開關/i指定的目錄。上圖中,有兩項/i。會依次在D:\inc1D:\inc2中查找。集成開發環境中,可以設定這些目錄。

5、如果在集成環境編譯,還會在設置的Include目錄中查找。至於它的實現,筆者猜測:集成開發環境調用rc.exe時,將Include目錄添加至/i命令開關。

3.3 引用文件

有些資源,如圖標,其實就是引用的圖標文件,如下面的語句:

IDR_MAINFRAME ICON DISCARDABLE "res\\t6.ico"

假如上面一行語句位於2.rc2,那么查找res\t6.ico的順序如下:

1、被編譯資源文件所在目錄。注意:rc.exe不會查找2.rc21.rc2所在目錄,它會認為這條語句位於被編譯的資源文件(1.rc)內。

2、當前目錄;

3、由命令開關/i指定的目錄。上圖中,有兩項/i。會依次在D:\inc1D:\inc2中查找。集成開發環境中,可以設定這些目錄。

4、如果在集成環境編譯,還會在設置的Include目錄中查找。

4連接

VC++6.0里連接就是調用C:\Program Files\Microsoft Visual Studio\VC98\Bin\link.exe將編譯生成的objres合成為一個exe文件或dll文件。

連接的時候可能還需要其他程序員生成的obj文件和lib文件,使用這些文件的方法有三種。

1、增加該文件至VC項目

4.1 增加文件至項目

該方法的優點就是簡單,缺點是不靈活。如這個方法很難處理這個要求:對於Debug版本需要連接TestD.lib,對於Release版需要連接Test.lib

2、修改項目設置

首先增加文件,如圖4.2和圖4.3所示。

如果需要,還可以指定 Additional library path。如圖4.2和圖4.4所示。VC++6.0連接程序時,首先在項目目錄(即dsp、vcp、vcproj文件所在目錄)下查找 Func.obj 和 Test.lib,其次在Additional library path下查找,最后在標准目錄下查找。標准庫文件目錄的設置請參考圖2.3和圖2.4。

 

4.2 VC++6.0增加庫文件及設置庫文件目錄

4.3 VC++7.0增加庫文件

4.4 VC++7.0設置庫文件目錄

3、在頭文件或源文件中,插入如下代碼:

#pragma comment(lib, "Test.lib")            //連接時使用 Test.lib。

接着指定 Additional library path,請參考方法2里的描述。連接器查找 Test.lib 時,其查找順序與第 2 種方法相同。

這種方法非常靈活,請見下面的代碼。其含義為:Debug版本下連接TestD.lib,Release版本下連接Test.lib。

#ifdef _DEBUG

#pragma comment(lib, "TestD.lib")

#else

#pragma comment(lib, "Test.lib")

#endif 

說明:

1、這種方法不能指定obj文件;

2、#pragma comment還可指定絕對路徑和相對路徑,但是建議不要這樣做。

5其它

5.1 編譯目錄

編譯、連接的時候會產生大量的文件,可以指定這些文件的存放路徑。

臨時目錄用來存放編譯過程中產生的文件,如:pchobjres文件。輸出目錄用來存放最終生成的exedll文件。這兩個目錄的設置如下圖所示。注意它們可以是絕對路徑,也可以是相對於dspvcpvcproj文件的相對路徑。

5.1 VC++6.0臨時、輸出目錄設置

 

 

 

 

 

 

 

5.2 VC++7.0臨時、輸出目錄設置

建議將臨時、輸出目錄設置為Temp,便於查找、刪除這些文件。

還可以指定目標文件,請參考下圖。

5.3 VC++6.0設置目標文件

5.4 VC++7.0設置目標文件

5.2 編譯事件

編譯的時候有三個事件:

1Pre-Build

開始編譯、連接的時候發生該事件。VC++7.0以上的版本才支持此事件。

2Pre-Link

編譯完畢,准備連接的時候發生該事件。

3Post-Build

編譯、連接都結束的時候發生該事件。

假如需要在程序編譯完成的時候將exe文件移動到c:\,可在Post-Build里增加DOS命令:move $(TargetPath) c:\。具體的設置請參考下圖。

5.5 VC++6.0增加編譯后處理命令

 

 

 

 

 

 

 

 

 

 

 

 

 

5.6 VC++7.0增加編譯后處理命令

$(TargetPath)是編譯時產生的環境變量,其它的環境變量及含義見下表

環境變量

$(MSDEVDIR)

Microsoft Developer目錄,如:C:\Program Files\Microsoft Visual Studio\COMMON\MSDev98

$(IntDir) 

臨時目錄

$(OutDir) 

輸出目錄

$(TargetPath) 

目標文件,包括路徑

$(TargetDir) 

目標文件所在目錄

$(TargetName)

目標文件名,不包括路徑和擴展名

5.3 自定義編譯

有沒有想過在VC++6.0里編譯VC#代碼?有了Custom Build一切皆有可能。假定有如下VC#代碼,存在於文件1.cs

using System;

using System.Windows.Forms;

static class Program

{

static void Main()

{

MessageBox.Show("Hello VC#");

}

}

請將1.cs添加至VC++6.0工程,並設置其Custom Build屬性:

Commands有兩條命令,第一行為:

C:\WINDOWS\Microsoft.NET\Framework\v3.5\Csc.exe /out:$(InputDir)\$(InputName).exe $(InputPath)

其實就是調用csc程序,編譯1.cs文件,生成1.exe文件。環境變量$(InputPath)就是1.cs相對於dsp文件的路徑(包括文件名)。環境變量$(InputDir)$(InputPath)的目錄部分。環境變量$(InputName)1.cs的文件名,不包括擴展名,其實就是1了。$(InputDir)\$(InputName).exe其實就是與1.cs在同一目錄下的文件1.exe

第二行命令為$(InputDir)\$(InputName).exe,其實就是編譯結束后運行這個程序。

Outputs里為輸出文件,這里就是$(InputDir)\$(InputName).exe了。

編譯后,可以看到運行結果。

5.7 編譯VC#

可以猜測到Custom Build的編譯步驟:

1、刪除輸出文件,這里就是1.exe

2、設置當前目錄為dsp所在目錄;

3、設置環境變量;

4、調用Commands里面的命令。命令的輸出全部被重定向至VC++6.0Output窗口,這樣就可以在IDE里查看編譯結果。

 

5.4 預定義宏

對於VC++而言,預定義宏分為兩大類:ANSI C 預定義宏、微軟C++預定義宏。前者被絕大多數C++編譯器支持,后者只被微軟的VC++支持。

5.4.1 ANSI C 預定義宏

__DATE__

文件的修改日期(本地時間)asctime的返回值

"Oct 31 2009"

__FILE__

文件名,ANSI編碼。編譯時/FC控制是否含目錄。

下面的__WFILE__將是Unicode編碼的文件名

#define WIDEN2(x) L ## x

#define WIDEN(x) WIDEN2(x)

#define __WFILE__ WIDEN(__FILE__)

"c:\\vcproj\\a.c"

__LINE__

所在的行號,是10進制的整數。可以被#line預編譯指令修改

5

__STDC__

表示編寫的C代碼必須符合ANSI C標准。不能編譯C++代碼。

 

__TIME__

文件的修改時刻(本地時間)

"12:48:06"

__TIMESTAMP__

文件的修改日期時刻(本地時間)

"Sat Oct 31 12:48:06 2009"

 

5.4.2 微軟C++預定義宏

_ATL_VER 

ATL版本

_CHAR_UNSIGNED

char為無符號。指定/J后,該宏被定義

__CLR_VER 

CLR(common language runtime)版本,其格式為Mmmbbbbb

M 是主版本號

mm 是次版本號

bbbbb 是編譯版本號

__cplusplus_cli 

Defined when compiling with /clr, /clr:pure, or /clr:safe. Value of __cplusplus_cli is 200406. __cplusplus_cli is in effect throughout the translation unit.

__COUNTER__ 

0開始,出現一次增加1。可以用來產生讀一無二的變量名:

// pre_mac_counter.cpp

#include <stdio.h>

#define FUNC2(x,y) x##y

#define FUNC1(x,y) FUNC2(x,y)

#define FUNC(x) FUNC1(x,__COUNTER__)

 

int FUNC(my_unique_prefix);

int FUNC(my_unique_prefix);

int main()

{

my_unique_prefix0 = 0;

printf_s("\n%d",my_unique_prefix0);

my_unique_prefix0++;

printf_s("\n%d",my_unique_prefix0);

} 

__cplusplus 

如果使用C++編譯器,則該宏被定義

_CPPLIB_VER

Defined if you include any of the C++ Standard Library headers; reports which version of the Dinkumware header files are present.

_CPPRTTI

編譯開關/GR被打開時,該宏被定義,表示支持運行時類型信息Run-Time Type Information

_CPPUNWIND

Defined for code compiled with /GX (Enable Exception Handling).

_DEBUG

Defined when compiling with /LDd, /MDd, and /MTd.

_DLL 

Defined when /MD or /MDd (Multithread DLL) is specified. 

__FUNCDNAME__ 

Valid only within a function and returns the decorated name of the enclosing function (as a string). __FUNCDNAME__ is not expanded if you use the /EP or /P compiler option.

__FUNCSIG__ 

Valid only within a function and returns the signature of the enclosing function (as a string). __FUNCSIG__ is not expanded if you use the /EP or /P compiler option.

On a 64-bit operating system, the calling convention is __cdecl by default. 

__FUNCTION__ 

Valid only within a function and returns the undecorated name of the enclosing function (as a string). __FUNCTION__ is not expanded if you use the /EP or /P compiler option.

_INTEGRAL_MAX_BITS  

Reports the maximum size (in bits) for an integral type. 

_M_ALPHA 

Defined for DEC ALPHA platforms (no longer supported). 

_M_CEE 

Defined for a compilation that uses any form of /clr (/clr:oldSyntax, /clr:safe, for example).

_M_CEE_PURE 

Defined for a compilation that uses /clr:pure. 

_M_CEE_SAFE 

Defined for a compilation that uses /clr:safe. 

_M_IX86 

Defined for x86 processors. See Values for _M_IX86 for more details.

_M_IX86 = 300        /G3    80386

_M_IX86 = 400        /G4    80486

_M_IX86 = 500        /G5    Pentium

_M_IX86 = 600        /G6    Pentium Pro, Pentium II, and Pentium III

_M_IX86 = 600        /GB    Blend(Default. Future compilers will emit a different value to

                    reflect the dominant processor.)

_M_IA64 

Defined for Itanium Processor Family 64-bit processors.

_M_IX86_FP 

Expands to a value indicating which /arch compiler option was used:

0 if /arch was not used.

1 if /arch:SSE was used.

2 if /arch:SSE2 was used.

See /arch (Minimum CPU Architecture) for more information. 

_M_MPPC  

Defined for Power Macintosh platforms (no longer supported).

_M_MRX000 

Defined for MIPS platforms (no longer supported). 

_M_PPC 

Defined for PowerPC platforms (no longer supported). 

_M_X64 

Defined for x64 processors. 

_MANAGED 

Defined to be 1 when /clr is specified. 

_MFC_VER

MFC的版本

0x0600        VC++6.0/EVC3.0/4.0

0x0700        VC++7.0(VC2002)

0x0710        VC++7.1(VC2003)

0x0800        VC++8.0(VC2005)

0x0900        VC++9.0(VC2008)

_MSC_EXTENSIONS 

This macro is defined when compiling with the /Ze compiler option (the default). Its value, when defined, is 1.

_MSC_VER

VC++的版本

1100    VC++5.0

1200    VC++6.0/EVC3.0

1201    EVC4.0

1300    VC++7.0(VC2002)

1310    VC++7.1(VC2003)

1400    VC++8.0(VC2005)

1500    VC++9.0(VC2008)

__MSVC_RUNTIME_CHECKS

Defined when one of the /RTC compiler options is specified.

_MT 

Defined when /MD or /MDd (Multithreaded DLL) or /MT or /MTd (Multithreaded) is specified.

_NATIVE_WCHAR_T_DEFINED

Defined when /Zc:wchar_t is used.

_OPENMP

Defined when compiling with /openmp, returns an integer representing the date of the OpenMP specification implemented by Visual C++.

_VC_NODEFAULTLIB  

Defined when /Zl is used; see /Zl (Omit Default Library Name) for more information.

_WCHAR_T_DEFINED 

Defined when /Zc:wchar_t is used or if wchar_t is defined in a system header file included in your project.

_WIN32 

Defined for applications for Win32 and Win64. Always defined.

_WIN64 

Defined for applications for Win64.

_Wp64 

Defined when specifying /Wp64.

UNDER_CE

_WIN32_WCE 

WinCE的版本

5.4.3 應用實例

下面的預處理指令將區分EVC++3.0EVC++4.0VC++6.0VC++9.0

#ifdef _WIN32_WCE        //智能設備

    #if _MSC_VER==1200        //EVC3.0

    #elif _MSC_VER==1201        //EVC4.0

    #elif _MSC_VER==1500        //VC++9.0,即VC2008

    #endif

#else

    #if _MSC_VER==1200        //VC++6.0

    #elif _MSC_VER==1500        //VC++9.0,即VC2008

    #endif

#endif

5.5 預處理器操作符

5.5.1 #

增加雙引號,如下面的預編譯指令

#define STR(x) #x

編譯時,STR(123)將被預處理器替換為 "123"

5.5.2 #@

增加單引號,如下面的預編譯指令

#define CHR(x) #@x

編譯時,CHR(A)將被預處理器替換為 'A'

5.5.3 ##

連接字符串,如下面的預編譯指令

#define CAT(x,y) x##y

編譯時,CAT(ABC,123) 將被預處理器替換為 ABC123

5.5.4 defined

必須與條件編譯語句#if……#elif……#endif一起使用。

如:#ifdef _WIN32_WCE #if defined(_WIN32_WCE) 等價。

如:#if defined(_WIN32_WCE) && _MSC_VER==1200 表示 EVC3.0 編譯器。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM