#pragma詳解(二)
每種C和C++的實現支援對其宿主機或作業系統唯一的功能。例如,一些程式需要精確控制超出資料所在的儲存空間,或著控制特定函式接受引數的方式。#pragma指示使每個編譯程式在保留C和C++語言的整體相容性時提供不同機器和作業系統特定的功能。編譯指示被定義為機器或作業系統特定的,並且通常每種編譯程式是不同的。
語法:
#pragma token_string
“token_string”是一系列字元用來給出所需的特定編譯程式指令和引數。數字符號“#”必須是包含編譯指令的行中第一個非空白字元;而空白字元可以隔開數字符號“#”和關鍵字“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連線方式說明的函式
由於不支援使用__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__ )