#pragma命令詳解
每種C和C++的實現支援對其宿主機或作業系統唯一的功能。例如,一些程式需要精確控制超出資料所在的儲存空間,或著控制特定函式接受引數的方式。#pragma指示使每個編譯程式在保留C和C++語言的整體相容性時提供不同機器和作業系統特定的功能。編譯指示被定義為機器或作業系統特定的,並且通常每種編譯程式是不同的。
語法:
#pragma token_string
“token_string”是一系列字元用來給出所需的特定編譯程式指令和引數。數字符號“#”必須是包含編譯指令的行中第一個非空白字元;而空白字元可以隔開數字符號“#”和關鍵字“pragma”。在#pragma後面,寫任何翻譯程式能夠作為預處理符號分析的文字。#pragma
如果編譯程式發現它不認得一個編譯指示,它將給出一個警告,可是編譯會繼續下去。
為了提供新的預處理功能,或者為編譯程式提供由實現定義的資訊,編譯指示可以用在一個條件語句內。C和C++編譯程式可以識別下列編譯程式指令。
alloc_text |
comment |
init_seg* |
optimize |
auto_inline |
component |
inline_depth |
pack |
bss_seg |
data_seg |
inline_recursion |
pointers_to_members* |
check_stack |
function |
intrinsic |
setlocale |
code_seg |
hdrstop |
message |
vtordisp* |
const_seg |
include_alias |
once |
warning |
*僅用於C++編譯程式。
1 alloc_text
#pragma alloc_text( "textsection", function1, ... )
命名特別定義的函式駐留的程式碼段。該編譯指示必須出現在函式說明符和函式定義之間。
alloc_text編譯指示不處理C++成員函式或過載函式。它僅能應用在以C連線方式說明的函式——就是說,函式是用extern
"C"
由於不支援使用__based的函式地址,需要使用alloc_text編譯指示來指定段位置。由textsection指定的名字應該由雙引號括起來。
alloc_text編譯指示必須出現在任何需要指定的函式說明之後,以及這些函式的定義之前。
在alloc_text編譯指示中引用的函式必須和該編譯指示處於同一個模組中。如果不這樣做,使以後一個未定義的函式被編譯到一個不同的程式碼段時,錯誤會也可能不會被捕獲。即使程式一般會正常執行,但是函式不會分派到應該在的段。
alloc_text的其它限制如下:
它不能用在一個函式內部。
它必須用於函式說明以後,函式定義以前。
2 auto_inline
#pragma auto_inline( [{on | off}] )
當指定off時將任何一個可以被考慮為作為自動嵌入擴充套件候選的函式排除出該範圍。為了使用auto_inline編譯指示,將其緊接著寫在一個函式定義之前或之後(不是在其內部)。該編譯指示將在其出現以後的第一個函式定義開始起作用。auto_inline編譯指示對顯式的inline函式不起作用。
3 bss_seg
#pragma data_seg( ["section-name"[, "section-class"] ] )
為未初始化資料指定預設段。data_seg編譯指示除了工作於已初始化資料而不是未初始化的以外具有一樣的效果。在一些情況下,你能使用bss_seg將所有未初始化資料安排在一個段中來加速你的裝載時間。
#pragma bss_seg( "MY_DATA" )
將導致把#pragma語句之後的未初始化的資料安排在一個叫做MY_DATA的段中。
用bss_seg編譯指示分配的資料不包含任何關於其位置的資訊。
第二個引數section-class是用於相容2.0版本以前的Visual C++的,現在將忽略它。
4 check_stack
#pragma check_stack([ {on | off}] )
#pragma check_stack{+ | –}
如果指定off(或者“-”)指示編譯程式關閉堆疊探測,或者指定on(或“+”)開啟堆疊探測。如果沒有給出引數,堆疊探測將根據預設設定決定。該編譯指示將在出現該指示之後的第一個函式開始生效。堆疊探測既不是巨集和能夠生成嵌入程式碼函式的一部分。
如果你沒有給出check_stack編譯指示的引數,堆疊檢查將恢復到在命令列指定的行為。詳細情況見編譯程式參考。#pragma check_stack和/Gs選項的互相作用情況在表2.1中說明。
表 2.1 使用check_stack編譯指示
編譯指示 |
用/Gs選項編譯? |
行為 |
#pragma check_stack()或#pragma check_stack |
是 |
後續的函式關閉堆疊檢查 |
#pragma check_stack()或#pragma check_stack |
否 |
後續的函式開啟堆疊檢查 |
#pragma check_stack(on)或#pragma check_stack(+) |
是或者否 |
後續的函式開啟堆疊檢查 |
#pragma check_stack(off)或#pragma check_stack(-) |
是或者否 |
後續的函式關閉堆疊檢查 |
5 code_seg
#pragma code_seg( ["section-name"[,"section-class"] ] )
指定分配函式的程式碼段。code_seg編譯指示為函式指定預設的段。你也能夠像段名一樣指定一個可選的類名。使用沒有段名字串的#pragma code_seg將恢復分配到編譯開始時候的狀態。
6 const_seg
#pragma const_seg( ["section-name"[, "section-class"] ] )
指定用於常量資料的預設段。data_seg編譯指示除了可以工作於所有資料以外具有一樣的效果。你能夠使用該編譯指示將你的常量資料儲存在一個只讀的段中。
#pragma const_seg( "MY_DATA" )
導致在#pragma語句後面的常量資料分配在一個叫做MY_DATA的段中。
用const_seg編譯指示分配的資料不包含任何關於其位置的資訊。
第二個引數section-class是用於相容2.0版本以前的Visual C++的,現在將忽略它。
7 comment
#pragma comment( comment-type [, commentstring] )
將描述記錄安排到目標檔案或可執行檔案中去。comment-type是下面說明的五個預定義識別符號中的一個,用來指定描述記錄的型別。可選的commentstring是一個字串文字值用於為一些描述型別提供附加的資訊。因為commentstring是一個字串文字值,所以它遵從字串文字值的所有規則,例如換碼字元、嵌入的引號(")和聯接。
7-1 compiler
在目標檔案中放置編譯程式名和版本號。該描述記錄被連線程式忽略。如果你為這個記錄型別提供一個commentstring引數,編譯程式將生成一個警告。
7-2 exestr
將commentstring放置到目標檔案中去。在連結時,這個字串再被放到可執行檔案去中。當可執行檔案被裝載時這個字串不會被裝入記憶體,然而,它可以被一個能夠在檔案中搜索可列印字串的程式找到。該描述記錄的一個用處是在可執行檔案中嵌入版本號或者類似的資訊。
7-3 lib
將一個庫搜尋記錄放置到目標檔案中去。該描述型別必須有包含你要連線程式搜尋的庫名(和可能的路徑)的commentstring引數。因為在目標檔案中該庫名先於預設的庫搜尋記錄,所以連線程式將如同你在命令列輸入這些庫一樣來搜尋它們。你可以在一個原始檔中放置多個庫搜尋記錄,每個記錄將按照它們出現在原始檔中的順序出現在目標檔案中。
7-4 linker
在目標檔案中放置連線程式選項。你可以用這個描述型別指定連線程式選項來代替在Project Setting對話方塊中Link頁內的選項。例如,你可以指定/include選項以強迫包含一個符號:
#pragma comment(linker, "/include:__mySymbol")
7-5 user
在目標檔案中包含一個普通描述記錄。commentstring引數包含描述的文字。該描述記錄將被連線程式忽略。
下面的編譯指示導致連線程式在連線時搜尋EMAPI.LIB庫。連線程式首先在當前工作目錄然後在LIB環境變數指定的路徑中搜索。
#pragma comment( lib, "emapi" )
下面的編譯指示導致編譯程式將其名字和版本號放置到目標檔案中去。
The following pragma causes the compiler to place the name and version number of the compiler in the object file:
#pragma comment( compiler )
注意,對於具有commentstring引數的描述記錄,你可以使用其它用作字串文字量的巨集來提供巨集擴充套件為字串文字量。你也能夠聯結任何字串文字量和巨集的組合來擴充套件成為一個字串文字量。例如,下面的語句是可以接受的:
#pragma comment( user, "Compiled on " __DATE__ " at " __TIME__ )
8 component
#pragma component( browser, { on | off }[, references [, name ]] )
#pragma component( minrebuild, on | off )
從原始檔內控制瀏覽資訊和依賴資訊的收集。
8-1 瀏覽資訊(Browser)
你可以將收集開啟或關閉,你也可以指定收集時忽略特別的名字。
使用on或off在編譯指示以後控制瀏覽資訊的收集。例如:
#pragma component(browser, off)
終止編譯程式收集瀏覽資訊。
注意,為了用這個編譯指示開啟瀏覽資訊的收集,必須先從Project Setting對話方塊或者命令列允許瀏覽資訊。
references選項可以有也可以沒有name引數。使用沒有name引數的references選項將開啟或者關閉引用資訊的收集(然而繼續收集其它瀏覽資訊)。例如:
#pragma component(browser, off, references)
終止編譯程式收集引用資訊。
使用有name和off引數的references選項將阻止從瀏覽資訊視窗中出現引用到的名字。用這個語法將忽略你不感興趣的名字和型別從而減少瀏覽資訊檔案的大小。例如:
#pragma component(browser, off, references, DWORD)
從這一點以後忽略DWORD的引用。你能夠用on恢復DWORD的引用收集:
#pragma component(browser, on, references, DWORD)
這是唯一的方法可以恢復收集指定名字的引用,你必須顯式地開啟任何你關閉的名字。
為了防止預處理程式副檔名字(就像擴充套件NULL到0),用引號括起來:
#pragma component(browser, off, references, "NULL")
8-2 最小化重建(Minimal Rebuild)
Visual C++的最小化重建功能要求編譯程式建立並儲存需要大量磁碟空間的C++類依賴資訊。為了節省磁碟空間,你能夠在你不需要收集依賴資訊時使用#pragma component(minrebuild,off),例如,沒有改變過標頭檔案。在未修改過的類之後插入#pragma component(minrebuild,on)重新開啟依賴資訊。
詳見Enable Minimal Rebuild(/Gm)編譯程式選項。
9 data_seg
#pragma data_seg( ["section-name"[, "section-class"] ] )
指定資料的預設段。例如:
#pragma data_seg( "MY_DATA" )
導致在#pragma語句後分配的資料儲存在一個叫做MY_DATA的段中。
用data_seg編譯指示分配的資料不包含任何關於其位置的資訊。
第二個引數section-class是用於相容2.0版本以前的Visual C++的,現在將忽略它。
10 function
#pragma function( function1 [, function2, ...] )
指定必須生成對編譯指示中引數列表內函式的呼叫。如果你使用intrinsic編譯指示(或者/Oi)來告訴編譯程式生成內含函式(內含函式如同嵌入程式碼一樣生成,不作為一個函式呼叫),你能夠用function編譯指示顯式地強迫函式呼叫。當遇到一個function編譯指示,它將在其後面遇到的第一個包含有內含函式的函式定義處生效。其持續作用到原始檔的尾部或者出現對同一個內含函式指定intrinsic編譯指示。function編譯指示只能用於函式外——在全域性層次。
為了列出具有內含形式的函式表,參見#pragma intrinsic。
11 hdrstop
#pragma hdrstop [( "filename" )]
控制預編譯標頭檔案的工作方式。filename是要使用或者建立(依賴於是否指定了/Yu或/Yc)預編譯標頭檔案的名字。如果 filename不包括一個指定路徑,將假定預編譯標頭檔案和原始檔處於同一個目錄中。當指定自動預編譯標頭檔案選項/YX時,所有指定的檔名將被忽略。
如果有/YX或者/Yc選項,而且C或C++檔案包含了一個hdrstop編譯指示時,編譯程式儲存編譯指示之前的編譯狀態。編譯指示之後的編譯狀態不被儲存。
hdrstop編譯選項不能出現在一個頭檔案內。它只能出現在原始檔的檔案級,它也不能出現在任何資料或者函式的說明或定義之中。
注意,除非指定沒有檔名的/YX選項或者/Yu或/Yc選項,否則hdrstop編譯指示將被忽略。
用一個檔名命名要儲存編譯狀態的預編譯標頭檔案。在hdrstop和filename之間的空格是可選的。在hdrstop編譯指示中的檔名是一個字串,這樣它服從於C或C++的字串規則。特別的,你必須像下面例子裡面顯示的用引號括起來。
#pragma hdrstop( "c:\projects\include\myinc.pch" )
預編譯標頭檔案的檔名按照如下規則決定,按照優先次序:
/Fp編譯程式選項的引數;
由#pragma hdrstop的filename引數;
原檔名的基本檔名加上.PCH副檔名。
12 include_alias
#pragma include_alias( "long_filename", "short_filename" )
#pragma include_alias( <long_filename>, <short_filename> )
指定作為long_filename別名的short_filename。一些檔案系統允許超出8.3FAT檔案系統限制的長標頭檔案名。編譯程式不能簡單地將長檔名截斷為8.3名字,因為長標頭檔案名的前8個字元可能不是唯一的。無論何時編譯程式遇到long_filename串,它代替short_filename,並且用short_filename搜尋標頭檔案。這個編譯指示必須出現在相應的#include指示之前。例如:
// First eight characters of these two files not unique.
#pragma include_alias( "AppleSystemHeaderQuickdraw.h", "quickdra.h" )
#pragma include_alias( "AppleSystemHeaderFruit.h", "fruit.h" )
#pragma include_alias( "GraphicsMenu.h", "gramenu.h" )
#include "AppleSystemHeaderQuickdraw.h"
#include "AppleSystemHeaderFruit.h"
#include "GraphicsMenu.h"
這個別名在搜尋時精確匹配,包括拼寫和雙引號、尖括號。include_alias編譯指示在檔名上執行簡單的字串匹配,不進行其它的檔名驗證。例如,給出下列指示:
#pragma include_alias("mymath.h", "math.h")
#include "./mymath.h"
#include "sys/mymath.h"
並不執行別名替代,因為標頭檔案名字串沒有精確匹配。另外,在/Yu,/Yc和/YX編譯程式選項,或hdrstop編譯指示中作為引數的標頭檔案名不被替換。例如,如果你的原始檔包含下列指示:
#include <AppleSystemHeaderStop.h>
相應的編譯程式選項必須是:
/YcAppleSystemHeaderStop.h
你能夠用include_alias編譯指示將任何標頭檔案對映到其它檔案。例如:
#pragma include_alias( "api.h", "c:\version1.0\api.h" )
#pragma include_alias( <stdio.h>, <newstdio.h> )
#include "api.h"
#include <stdio.h>
不要混淆用雙引號和尖括號括起來的檔名。例如,給出上面的#pragma include_alias指示時,在下面的#include指示中編譯程式不執行替換。
#include <api.h>
#include "stdio.h"
還有,下面的指示將產生一個錯誤:
#pragma include_alias(<header.h>, "header.h") // Error
注意,在錯誤資訊中報告的檔名,或者預定義巨集__FILE__的值,是執行替換以後的檔名。例如,在下列指示之後:
#pragma include_alias( "VeryLongFileName.H", "myfile.h" )
#include "VeryLongFileName.H"
檔案VeryLongFileName.H產生下列錯誤資訊:
myfile.h(15) : error C2059 : syntax error
還要注意的是不支援傳遞性。給出下面的指示:
#pragma include_alias( "one.h", "two.h" )
#pragma include_alias( "two.h", "three.h" )
#include "one.h"
編譯程式將搜尋two.h而不是three.h。
13 init_seg
C++特有
#pragma init_seg({ compiler | lib | user | "section-name" [, "func-name"]} )
指定影響啟動程式碼執行的關鍵字或程式碼段。因為全域性靜態物件的初始化可以包含執行程式碼,所以你必須指定一個關鍵字來定義什麼時候構造物件。在使用需要初始化的動態連線庫(DLL)或程式庫時使用init_seg編譯指示是尤其重要的。
init_seg編譯指示的選項有:
13-1 compiler
由Microsoft C執行時間庫保留。在這個組中的物件將第一個構造。
13-2 lib
用於第三方類庫開發者的初始化。在這個組中的物件將在標記為構造compiler的物件之後,其它物件之前構造。
13-3 user
用於任何其它使用者。在這個組中的物件將最後構造。
13-4 section-name
允許顯式地指定初始化段。在使用者指定的section-name中的物件將不會隱式地構造,而它們的地址將會被放置在由section-name命名的段中。
13-5 func-name
指定當程式退出時,作為atexit函式呼叫的函式。這個函式必須具有和atexit函式相同的形式:
int funcname(void (__cdecl *)(void));
如果你需要延遲初始化,你能夠選擇指定顯式的段名。隨後你必須呼叫每個靜態物件的建構函式。
14 inline_depth
#pragma inline_depth( [0... 255] )
通過控制能夠被擴充套件的一系列函式呼叫(從0到255次)來控制嵌入函式擴充套件的發生次數,這個編譯指示控制用inline,__inline標記的或在/Ob2選項下能自動嵌入的嵌入函式。
inline_depth編譯指示控制能夠被擴充套件的一系列函式呼叫。例如,如果嵌入深度是4,並且如果A呼叫B然後呼叫C,所有的3次呼叫都將做嵌入擴充套件。然而,如果設定的最近一次嵌入深度是2,則只有A和B被擴充套件,而C仍然作為函式呼叫。
為了使用這個編譯指示,你必須設定編譯程式選項/Ob為1或者2。用這個編譯指示指定的深度設定在該指示後面的第一個函式開始生效。如果你在括號內不指定一個值,inline_depth設定嵌入深度到預設值8。
在擴充套件時,嵌入深度可以被減少而不能被增加。如果嵌入深度是6,同時在擴充套件過程中預處理程式遇到一個inline_depth編譯指示設定為8,則深度保持為6。
嵌入深度0將拒絕嵌入擴充套件,深度255將設定在嵌入擴充套件時沒有限制。如果用一個沒有指定值的編譯指示,則使用為預設值。
15 inline_recursion
#pragma inline_recursion( [{on | off}] )
控制直接或者相互間的遞迴函式呼叫式的嵌入擴充套件。用這個編譯指示控制用inline,__inline標記的或在/Ob2選項下能自動嵌入的嵌入函式。使用這個編譯指示需要設定編譯程式選項/Ob為1或者2。預設的inline_recursion狀態是off。這個編譯指示在出現該編譯指示之後第一個函式呼叫起作用,並不影響函式的定義。
inline_recursion編譯指示控制如何擴充套件遞迴函式。如果inline_recursion是off,並且如果一個嵌入函式呼叫了它自己(直接的或者間接的),函式將僅僅擴充套件一次。如果inline_recursion是on,函式將擴充套件多次直到達到inline_depth的值或者容量限制。
16 intrinsic
#pragma intrinsic( function1 [, function2, ...] )
指定對在編譯指示引數表中函式呼叫是內含的。編譯程式像嵌入程式碼一樣生成內含函式,而不是函式呼叫。下面列出了具有內含形式的庫函式。一旦遇到intrinsic編譯指示,它從第一個包含指定內含函式的函式定義開始起作用。作用持續到原始檔尾部或者出現包含相同內含函式的function編譯指示。intrinsic編譯指示只能用在函式定義外——在全域性層次。
下列函式具有內含形式:
_disable |
_enable |
_inp |
_inpw |
_lrotl |
_lrotr |
_outp |
_outpw |
_rotl |
_rotr |
_strset |
abs |
fabs |
labs |
memcmp |
memcpy |
memset |
strcat |
strcmp |
strcpy |
strlen |
使用內含函式的程式更快,因為它們沒有函式呼叫的額外代價,然而因為有附加的程式碼生成,可能比較大。
注意,_alloca和setjmp函式總是內含的,這個行為不受intrinsic編譯指示影響。
下列浮點函式沒有內含形式。然而它們具有直接將引數通過浮點晶片傳送而不是推入程式堆疊的版本。
acos |
asin |
cosh |
fmod |
pow |
sinh |
tanh |
當你同時指定/Oi和/Og編譯程式選項(或者任何包含/Og,/Ox,/O1和/O2的選項)時下列浮點函式具有真正的內含形式。
atan |
exp |
log10 |
sqrt |
atan2 |
log |
sin |
tan |
cos |
你可以用編譯程式選項/Op或/Za來覆蓋真內含浮點選項的生成。在這種情況下,函式會像一般庫函式一樣被生成,同時直接將引數通過浮點晶片傳送而不是推入程式堆疊。
17 message
#pragma message( messagestring )
不中斷編譯,傳送一個字串文字量到標準輸出。message編譯指示的典型運用是在編譯時顯示資訊。
下面的程式碼段用message編譯指示在編譯過程中顯示一條資訊:
#if _M_IX86 == 500
#pragma message( "Pentium processor build" )
#endif
messagestring引數可以是一個能夠擴充套件成字串文字量的巨集,並且你能夠用字串文字量和巨集的任何組合來構造。例如,下面的語句顯示被編譯檔案的檔名和檔案最後一次修改的日期和時間。
#pragma message( "Compiling " __FILE__ )
#pragma message( "Last modified on " __TIMESTAMP__ )
18 once
#pragma once
指定在建立過程中該編譯指示所在的檔案僅僅被編譯程式包含(開啟)一次。該編譯指示的一種常見用法如下:
//header.h
#pragma once
// Your C or C++ code would follow:
19 optimize
僅在專業版和企業版中存在
#pragma optimize( "[optimization-list]", {on | off} )
程式碼優化僅有Visual C++專業版和企業版支援。詳見Visual C++ Edition。
指定在函式層次執行的優化。optimize編譯選項必須在函式外出現,並且在該編譯指示出現以後的第一個函式定義開始起作用。on和off引數開啟或關閉在optimization-list指定的選項。
optimization-list能夠是0或更多個在表2.2中給出的引數:
表 2.2 optimize編譯指示的引數
引數 |
優化型別 |
a |
假定沒有別名。 |
g |
允許全域性優化。 |
p |
增強浮點一致性。 |
s 或 t |
指定更短或者更快的機器程式碼序列。 |
w |
假定在函式呼叫中沒有別名。 |
y |
在程式堆疊中生成框架指標。 |
這些和在/O編譯程式選項中使用的是相同的字母。例如:
#pragma optimize( "atp", on )
用空字串("")的optimize編譯指示是一種特別形式。它要麼關閉所有的優化選項,要麼恢復它們到原始(或預設)的設定。
#pragma optimize( "", off )
#pragma optimize( "", on )
20 pack
#pragma pack( [ n] )
指定結構和聯合成員的緊縮對齊。儘管用/Zp選項設定整個翻譯單元的結構和聯合成員的緊縮對齊,可以用pack編譯指示在資料說明層次設定緊縮對齊。從出現該編譯指示後的第一個結構或者聯合說明開始生效。這個編譯指示不影響定義。
當你使用#pragma pack(n),其中n是1,2,4,8或者16,第一個以後的每個結構成員儲存在較小的成員型別或者n位元組邊界上。如果你使用沒有引數的#pragma pack,結構成員將被緊縮到由/Zp指定的值。預設的/Zp緊縮的大小是/Zp8。
編譯程式還支援下面的增強語法:
#pragma pack( [ [ { push | pop}, ] [ identifier, ] ] [ n ] )
該語法允許你將使用不同緊縮編譯指示的元件合併到同一個翻譯單元內。
每次出現有push引數的pack編譯指示將儲存當前的緊縮對齊值到一個內部的編譯程式堆疊。編譯指示的引數列表從左向右讀取。如果你使用了push,當前緊縮值被儲存。如果你提供了一個n值,這個值將成為新的緊縮值。如果你指定了一個你選定的標示符,這個標示符將和新的緊縮值關聯。
每次出現有pop引數的pack編譯指示從內部編譯程式堆疊頂部取出一個值並將那個值作為新的緊縮對齊。如果你用了pop,而內部編譯程式堆疊是空的,對齊值將從命令列得到,同時給出一個警告。如果你用了pop並指定了n的值,那個值將成為新的緊縮值。如果你用了pop並指定了一個標示符,將移去所有儲存在堆疊中的的值直到匹配的找到匹配的標示符,和該標示符關聯的緊縮值也被從堆疊中移出來成為新的緊縮值。如果沒有找到匹配的標示符,將從命令列獲取緊縮值併產生一個1級警告。預設的緊縮對齊是8。
pack編譯指示的新的增強功能允許你編寫標頭檔案保證在使用標頭檔案之前和其後的緊縮值是一樣的:
/* File name: include1.h
*/
#pragma pack( push, enter_include1 )
/* Your include-file code ... */
#pragma pack( pop, enter_include1 )
/* End of include1.h */
在前面的例子中,進入標頭檔案時將當前緊縮值和標示符enter_include1關聯並推入,被記住。在標頭檔案尾部的pack編譯選項移去所有在標頭檔案中可能遇到的緊縮值並移去和enter_include1關聯的緊縮值。這樣標頭檔案保證了在使用標頭檔案之前和其後的緊縮值是一樣的。
新功能也允許你在你的程式碼內用pack編譯指示為不同的程式碼,例如標頭檔案設定不同的緊縮對齊。
#pragma pack( push, before_include1 )
#include "include1.h"
#pragma pack( pop, before_include1 )
在上一個例子中,你的程式碼受到保護,防止了在include.h中的任何緊縮值的改變。
21 pointers_to_members
C++特有
#pragma pointers_to_members(pointer-declaration, [most-general-representation] )
指定是否能夠在相關類定義之前說明一個指向類成員的指標,並且用於控制指標的大小和解釋指標的程式碼。你能夠在你的原始碼中使用pointers_to_members編譯知識來代替/vmx編譯程式選項。
pointer-declaration引數指出是否在相關函式定義之前或其後你已經說明了一個指向成員的指標。pointer-declaration引數是下面兩個符號之一:
引數 |
說明 |
full_generality |
生成安全的,但是有時不能優化的程式碼。如果有一些指向成員的指標在相關類定義之前說明,你要用full_generality。這個引數總是使用由most-general-representation指定的指標表示方式。 |
best_case |
對於所有指向成員的指標用最佳的表示方式生成安全的,優化的程式碼。需要在說明一個指向類成員指標之前定義類。預設是best_case。 |
most-general-representaion引數指出在一個翻譯單元中編譯程式能夠安全引用任何指向類成員指標的最小指標表示方式。這個引數可以是下列之一:
引數 |
說明 |
single_inheritance |
最普通的表示方式是單繼承,指向成員函式。如果用於指向具有多重或者虛擬繼承方式類成員的指標,將產生一個錯誤。 |
multi_inheritance |
最普通的表示方式是多重繼承,指向成員函式。如果用於指向具有虛擬繼承方式類成員的指標,將產生一個錯誤。 |
virtual_inheritance |
最普通的表示方式是虛擬繼承,指向成員函式。不會產生錯誤。當使用#pragma pointers_to_members (full_generality)時這是預設的引數。 |
22 setlocale
#pragma setlocale( "locale-string" )
定義用於翻譯寬字元常數和字串文字量時用的地區(國家和語言)。由於用於從多位元組字元轉換到寬字元的演算法根據地區或者由於在執行可執行程式不同的地方進行編譯而不同,這個編譯指示提供一種在編譯時指定目標地區的方式。這保證寬字元字串將以正確的格式儲存。預設的locale-string是“C”。“C”地區將字串中的每個字元作為wchar_t(即unsigned int)對映其值。
23 vtordisp
C++特有
#pragma vtordisp({on | off} )
允許隱藏的附加vtordisp建構函式/解構函式替換成員。vtordisp編譯指示僅能夠用於具有虛擬基類的程式碼。如果派生類從一個虛擬基類過載了一個虛擬函式,並且如果派生類的建構函式或解構函式用指向虛擬基類的指標呼叫了這個函式,編譯程式將根據虛擬基類在類中引入一個附加的隱藏“vtordisp”域。
vtodisp編譯選項影響它後面的類佈局。/vd0和/vd1選項為整個模組指定了相同的行為。指定off將禁止隱藏的vtordisp成員,指定on(預設)將在它們需要的時候允許vtordisp。僅在不可能出現類的建構函式和解構函式通過this指標呼叫其指向物件中的虛擬函式時才關閉vtordisp。
#pragma vtordisp( off )
class GetReal : virtual public { ... };
#pragma vtordisp( on )
24 warning
#pragma warning( warning-specifier : warning-number-list [,warning-specifier : warning-number-list...] )
#pragma warning( push[ , n ] )
#pragma warning( pop )
允許有選擇地修改編譯程式警告資訊的行為。
warning-specifier能夠是下列值之一:
warning-specifier |
含義 |
once |
只顯示指定資訊一次。 |
default |
對指定資訊應用預設的編譯程式選項。 |
1,2,3,4 |
對指定資訊引用給定的警告等級。 |
disable |
不顯示指定資訊。 |
error |
對指定資訊作為錯誤顯示。 |
warning-number_list能夠包含任何警告編號。如下,在一個編譯指示中可以指定多個選項:
#pragma warning( disable : 4507 34; once : 4385; error : 164 )
這等價於:
#pragma warning( disable : 4507 34 ) // Disable warning messages
// 4507 and 34.
#pragma warning( once : 4385 ) // Issue warning 4385
// only once.
#pragma warning( error : 164 ) // Report warning 164
// as an error.
對於那些關於程式碼生成的,大於4699的警告標號,warning編譯指示僅在函式定義外時有效。如果指定的警告編號大於4699並且用於函式內時被忽略。下面例子說明了用warning編譯指示禁止、然後恢復有關程式碼生成警告資訊的正確位置:
int a;
#pragma warning( disable : 4705 )
void func()
{
a;
}