預(yù)處理 #pragma 命令詳解
掃描二維碼
隨時隨地手機(jī)看文章
素材來源:網(wǎng)絡(luò)
編輯整理:strongerHuang
預(yù)處理指令?#pragma 相信程序員都知道,但在所有的預(yù)處理指令中,#pragma 指令可能是最復(fù)雜的了,它的作用是設(shè)定編譯器的狀態(tài)或者是指示編譯器完成一些特定的動作。
#pragma指令對每個編譯器給出了一個方法,在保持與C和C++語言完全兼容的情況下,給出主機(jī)或操作系統(tǒng)專有的特征。依據(jù)定義,編譯指示是機(jī)器或操作系統(tǒng)專有的,且對于每個編譯器都是不同的。
語法:
#pragma Para
(其中Para 為參數(shù))
比如:
#pragma once
指定在創(chuàng)建過程中該編譯指示所在的文件僅僅被編譯程序包含(打開)一次。
下面羅列#pragma常見命令:
其中:* 僅用于C++編譯程序。
下面分享一下每個指令含義:
1 alloc_text
#pragma alloc_text( "textsection", function1, ... )命名特別定義的函數(shù)駐留的代碼段。該編譯指示必須出現(xiàn)在函數(shù)說明符和函數(shù)定義之間。
alloc_text編譯指示不處理C++成員函數(shù)或重載函數(shù)。它僅能應(yīng)用在以C連接方式說明的函數(shù)——就是說,函數(shù)是用extern "C"連接指示符說明的。如果你試圖將這個編譯指示應(yīng)用于一個具有C++連接方式的函數(shù)時,將出現(xiàn)一個編譯程序錯誤。
由于不支持使用__based的函數(shù)地址,需要使用alloc_text編譯指示來指定段位置。由textsection指定的名字應(yīng)該由雙引號括起來。
alloc_text編譯指示必須出現(xiàn)在任何需要指定的函數(shù)說明之后,以及這些函數(shù)的定義之前。
在alloc_text編譯指示中引用的函數(shù)必須和該編譯指示處于同一個模塊中。如果不這樣做,使以后一個未定義的函數(shù)被編譯到一個不同的代碼段時,錯誤會也可能不會被捕獲。即使程序一般會正常運(yùn)行,但是函數(shù)不會分派到應(yīng)該在的段。
alloc_text的其它限制如下:
它不能用在一個函數(shù)內(nèi)部。
它必須用于函數(shù)說明以后,函數(shù)定義以前。
2 auto_inline
#pragma auto_inline( [{on | off}] )當(dāng)指定off時將任何一個可以被考慮為作為自動嵌入擴(kuò)展候選的函數(shù)排除出該范圍。為了使用auto_inline編譯指示,將其緊接著寫在一個函數(shù)定義之前或之后(不是在其內(nèi)部)。該編譯指示將在其出現(xiàn)以后的第一個函數(shù)定義開始起作用。auto_inline編譯指示對顯式的inline函數(shù)不起作用。
3 bss_seg
#pragma data_seg( ["section-name"[, "section-class"] ] )為未初始化數(shù)據(jù)指定缺省段。data_seg編譯指示除了工作于已初始化數(shù)據(jù)而不是未初始化的以外具有一樣的效果。在一些情況下,你能使用bss_seg將所有未初始化數(shù)據(jù)安排在一個段中來加速你的裝載時間。
#pragma bss_seg( "MY_DATA" )
將導(dǎo)致把#pragma語句之后的未初始化的數(shù)據(jù)安排在一個叫做MY_DATA的段中。
用bss_seg編譯指示分配的數(shù)據(jù)不包含任何關(guān)于其位置的信息。
第二個參數(shù)section-class是用于兼容2.0版本以前的Visual C++的,現(xiàn)在將忽略它。
4 check_stack
#pragma check_stack([ {on | off}] ) #pragma check_stack{+ | –}如果指定off(或者“-”)指示編譯程序關(guān)閉堆棧探測,或者指定on(或“+”)打開堆棧探測。如果沒有給出參數(shù),堆棧探測將根據(jù)默認(rèn)設(shè)置決定。該編譯指示將在出現(xiàn)該指示之后的第一個函數(shù)開始生效。堆棧探測既不是宏和能夠生成嵌入代碼函數(shù)的一部分。
如果你沒有給出check-_stack編譯指示的參數(shù),堆棧檢查將恢復(fù)到在命令行指定的行為。詳細(xì)情況見編譯程序參考。#pragma check_stack和/Gs選項的互相作用情況在表2.1中說明。
表 2.1 使用 check_stack 編譯指示
5 code_seg
#pragma code_seg( ["section-name"[,"section-class"] ] )指定分配函數(shù)的代碼段。code_seg編譯指示為函數(shù)指定默認(rèn)的段。你也能夠像段名一樣指定一個可選的類名。使用沒有段名字符串的#pragma code_seg將恢復(fù)分配到編譯開始時候的狀態(tài)。
6 const_seg
#pragma const_seg( ["section-name"[, "section-class"] ] )指定用于常量數(shù)據(jù)的默認(rèn)段。data_seg編譯指示除了可以工作于所有數(shù)據(jù)以外具有一樣的效果。你能夠使用該編譯指示將你的常量數(shù)據(jù)保存在一個只讀的段中。
#pragma const_seg( "MY_DATA" )導(dǎo)致在#pragma語句后面的常量數(shù)據(jù)分配在一個叫做MY_DATA的段中。
用const_seg編譯指示分配的數(shù)據(jù)不包含任何關(guān)于其位置的信息。
第二個參數(shù)section-class是用于兼容2.0版本以前的Visual C++的,現(xiàn)在將忽略它。
7 comment
#pragma comment( comment-type [, commentstring] )將描述記錄安排到目標(biāo)文件或可執(zhí)行文件中去。comment-type是下面說明的五個預(yù)定義標(biāo)識符中的一個,用來指定描述記錄的類型??蛇x的commentstring是一個字符串文字值用于為一些描述類型提供附加的信息。因為commentstring是一個字符串文字值,所以它遵從字符串文字值的所有規(guī)則,例如換碼字符、嵌入的引號(")和聯(lián)接。
7-1 compiler在目標(biāo)文件中放置編譯程序名和版本號。該描述記錄被連接程序忽略。如果你為這個記錄類型提供一個commentstring參數(shù),編譯程序?qū)⑸梢粋€警告。
7-2 exestr將commentstring放置到目標(biāo)文件中去。在連結(jié)時,這個字符串再被放到可執(zhí)行文件去中。當(dāng)可執(zhí)行文件被裝載時這個字符串不會被裝入內(nèi)存,然而,它可以被一個能夠在文件中搜索可打印字符串的程序找到。該描述記錄的一個用處是在可執(zhí)行文件中嵌入版本號或者類似的信息。
7-3 lib將一個庫搜索記錄放置到目標(biāo)文件中去。該描述類型必須有包含你要連接程序搜索的庫名(和可能的路徑)的commentstring參數(shù)。因為在目標(biāo)文件中該庫名先于默認(rèn)的庫搜索記錄,所以連接程序?qū)⑷缤阍诿钚休斎脒@些庫一樣來搜索它們。你可以在一個源文件中放置多個庫搜索記錄,每個記錄將按照它們出現(xiàn)在源文件中的順序出現(xiàn)在目標(biāo)文件中。
7-4 linker在目標(biāo)文件中放置連接程序選項。你可以用這個描述類型指定連接程序選項來代替在Project Setting對話框中Link頁內(nèi)的選項。例如,你可以指定/include選項以強(qiáng)迫包含一個符號:
#pragma comment(linker, "/include:__mySymbol") 7-5 user在目標(biāo)文件中包含一個普通描述記錄。commentstring參數(shù)包含描述的文本。該描述記錄將被連接程序忽略。
下面的編譯指示導(dǎo)致連接程序在連接時搜索EMAPI.LIB庫。連接程序首先在當(dāng)前工作目錄然后在LIB環(huán)境變量指定的路徑中搜索。
#pragma comment( lib, "emapi" )下面的編譯指示導(dǎo)致編譯程序?qū)⑵涿趾桶姹咎柗胖玫侥繕?biāo)文件中去。
The following pragma causes the compiler to place the name and version number of the compiler in the object file:
#pragma comment( compiler )注意,對于具有commentstring參數(shù)的描述記錄,你可以使用其它用作字符串文字量的宏來提供宏擴(kuò)展為字符串文字量。你也能夠聯(lián)結(jié)任何字符串文字量和宏的組合來擴(kuò)展成為一個字符串文字量。例如,下面的語句是可以接受的:
#pragma comment( user, "Compiled on " __DATE__ " at " __TIME__ )
8 component
#pragma component( browser, { on | off }[, references [, name ]] ) #pragma component( minrebuild, on | off )
從源文件內(nèi)控制瀏覽信息和依賴信息的收集。
8-1 瀏覽信息(Browser )你可以將收集打開或關(guān)閉,你也可以指定收集時忽略特別的名字。
使用on或off在編譯指示以后控制瀏覽信息的收集。例如:
#pragma component(browser, off)
終止編譯程序收集瀏覽信息。
注意,為了用這個編譯指示打開瀏覽信息的收集,必須先從Project Setting對話框或者命令行允許瀏覽信息。
references選項可以有也可以沒有name參數(shù)。使用沒有name參數(shù)的references選項將打開或者關(guān)閉引用信息的收集(然而繼續(xù)收集其它瀏覽信息)。例如:
#pragma component(browser, off, references)
終止編譯程序收集引用信息。
使用有name和off參數(shù)的references選項將阻止從瀏覽信息窗口中出現(xiàn)引用到的名字。用這個語法將忽略你不感興趣的名字和類型從而減少瀏覽信息文件的大小。例如:
#pragma component(browser, off, references, DWORD)
從這一點以后忽略DWORD的引用。你能夠用on恢復(fù)DWORD的引用收集:
#pragma component(browser, on, references, DWORD)
這是唯一的方法可以恢復(fù)收集指定名字的引用,你必須顯式地打開任何你關(guān)閉的名字。
為了防止預(yù)處理程序擴(kuò)展名字(就像擴(kuò)展NULL到0),用引號括起來:
#pragma component(browser, off, references, "NULL")
8-2 最小化重建(Minimal Rebuild )Visual C++的最小化重建功能要求編譯程序創(chuàng)建并保存需要大量磁盤空間的C++類依賴信息。為了節(jié)省磁盤空間,你能夠在你不需要收集依賴信息時使用#pragma component(minrebuild,off),例如,沒有改變過頭文件。在未修改過的類之后插入#pragma component(minrebuild,on)重新打開依賴信息。
詳見Enable Minimal Rebuild(/Gm)編譯程序選項。
9 data_seg
#pragma data_seg( ["section-name"[, "section-class"] ] )指定數(shù)據(jù)的默認(rèn)段。例如:
#pragma data_seg( "MY_DATA" )導(dǎo)致在#pragma語句后分配的數(shù)據(jù)保存在一個叫做MY_DATA的段中。
用data_seg編譯指示分配的數(shù)據(jù)不包含任何關(guān)于其位置的信息。
第二個參數(shù)section-class是用于兼容2.0版本以前的Visual C++的,現(xiàn)在將忽略它。
10 function
#pragma function( function1 [, function2, ...] )指定必須生成對編譯指示中參數(shù)列表內(nèi)函數(shù)的調(diào)用。如果你使用intrinsic編譯指示(或者/Oi)來告訴編譯程序生成內(nèi)含函數(shù)(內(nèi)含函數(shù)如同嵌入代碼一樣生成,不作為一個函數(shù)調(diào)用),你能夠用function編譯指示顯式地強(qiáng)迫函數(shù)調(diào)用。當(dāng)遇到一個function編譯指示,它將在其后面遇到的第一個包含有內(nèi)含函數(shù)的函數(shù)定義處生效。其持續(xù)作用到源文件的尾部或者出現(xiàn)對同一個內(nèi)含函數(shù)指定intrinsic編譯指示。function編譯指示只能用于函數(shù)外——在全局層次。
為了列出具有內(nèi)含形式的函數(shù)表,參見#pragma intrinsic。
11 hdrstop
#pragma hdrstop [( "filename" )]控制預(yù)編譯頭文件的工作方式。filename是要使用或者創(chuàng)建(依賴于是否指定了/Yu或/Yc)預(yù)編譯頭文件的名字。如果 filename不包括一個指定路徑,將假定預(yù)編譯頭文件和源文件處于同一個目錄中。當(dāng)指定自動預(yù)編譯頭文件選項/YX時,所有指定的文件名將被忽略。
如果有/YX或者/Yc選項,而且C或C++文件包含了一個hdrstop編譯指示時,編譯程序保存編譯指示之前的編譯狀態(tài)。編譯指示之后的編譯狀態(tài)不被保存。
hdrstop編譯選項不能出現(xiàn)在一個頭文件內(nèi)。它只能出現(xiàn)在源文件的文件級,它也不能出現(xiàn)在任何數(shù)據(jù)或者函數(shù)的說明或定義之中。
注意,除非指定沒有文件名的/YX選項或者/Yu或/Yc選項,否則hdrstop編譯指示將被忽略。
用一個文件名命名要保存編譯狀態(tài)的預(yù)編譯頭文件。在hdrstop和filename之間的空格是可選的。在hdrstop編譯指示中的文件名是一個字符串,這樣它服從于C或C++的字符串規(guī)則。特別的,你必須像下面例子里面顯示的用引號括起來。
#pragma hdrstop( "c:\projects\include\myinc.pch" )
預(yù)編譯頭文件的文件名按照如下規(guī)則決定,按照優(yōu)先次序:
/Fp編譯程序選項的參數(shù);
由#pragma hdrstop的filename參數(shù);
原文件名的基本文件名加上.PCH擴(kuò)展名。
12 include_alias
#pragma include_alias( "long_filename", "short_filename" ) #pragma include_alias(,)指定作為long_filename別名的short_filename。一些文件系統(tǒng)允許超出8.3FAT文件系統(tǒng)限制的長頭文件名。編譯程序不能簡單地將長文件名截斷為8.3名字,因為長頭文件名的前8個字符可能不是唯一的。無論何時編譯程序遇到long_filename串,它代替short_filename,并且用short_filename搜索頭文件。這個編譯指示必須出現(xiàn)在相應(yīng)的#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編譯指示在文件名上執(zhí)行簡單的字符串匹配,不進(jìn)行其它的文件名驗證。例如,給出下列指示:
#pragma include_alias("mymath.h", "math.h")
#include "./mymath.h"
#include "sys/mymath.h"
并不執(zhí)行別名替代,因為頭文件名字符串沒有精確匹配。另外,在/Yu,/Yc和/YX編譯程序選項,或hdrstop編譯指示中作為參數(shù)的頭文件名不被替換。例如,如果你的源文件包含下列指示:
#include
相應(yīng)的編譯程序選項必須是:
/YcAppleSystemHeaderStop.h
你能夠用include-_alias編譯指示將任何頭文件映射到其它文件。例如:
#pragma include_alias( "api.h", "c:\version1.0\api.h" )
#pragma include_alias(
#include "api.h"
#include
不要混淆用雙引號和尖括號括起來的文件名。例如,給出上面的#pragma include_alias指示時,在下面的#include指示中編譯程序不執(zhí)行替換。
#include
#include "stdio.h"
還有,下面的指示將產(chǎn)生一個錯誤:
#pragma include_alias(
注意,在錯誤信息中報告的文件名,或者預(yù)定義宏__FILE__的值,是執(zhí)行替換以后的文件名。例如,在下列指示之后:
#pragma include_alias( "VeryLongFileName.H", "myfile.h" )
#include "VeryLongFileName.H"
文件VeryLongFileName.H產(chǎn)生下列錯誤信息:
myfile.h(15) : error C2059 : syntax error
還要注意的是不支持傳遞性。給出下面的指示:
#pragma include_alias( "one.h", "two.h" )
#pragma include_alias( "two.h", "three.h" )
#include "one.h"
編譯程序?qū)⑺阉?/span>two.h而不是three.h。
13 init_seg
C++特有 #pragma init_seg({ compiler | lib | user | "section-name" [, "func-name"]} )指定影響啟動代碼執(zhí)行的關(guān)鍵字或代碼段。因為全局靜態(tài)對象的初始化可以包含執(zhí)行代碼,所以你必須指定一個關(guān)鍵字來定義什么時候構(gòu)造對象。在使用需要初始化的動態(tài)連接庫(DLL)或程序庫時使用init_seg編譯指示是尤其重要的。
init_seg編譯指示的選項有:
13-1 compiler由Microsoft C運(yùn)行時間庫保留。在這個組中的對象將第一個構(gòu)造。
13-2 lib用于第三方類庫開發(fā)者的初始化。在這個組中的對象將在標(biāo)記為構(gòu)造compiler的對象之后,其它對象之前構(gòu)造。
13-3 user用于任何其它用戶。在這個組中的對象將最后構(gòu)造。
13-4 section-name允許顯式地指定初始化段。在用戶指定的section-name中的對象將不會隱式地構(gòu)造,而它們的地址將會被放置在由section-name命名的段中。
13-5 func-name指定當(dāng)程序退出時,作為atexit函數(shù)調(diào)用的函數(shù)。這個函數(shù)必須具有和atexit函數(shù)相同的形式:
int funcname(void (__cdecl *)(void));
如果你需要延遲初始化,你能夠選擇指定顯式的段名。隨后你必須調(diào)用每個靜態(tài)對象的構(gòu)造函數(shù)。
14 inline_depth
#pragma inline_depth( [0... 255] )通過控制能夠被擴(kuò)展的一系列函數(shù)調(diào)用(從0到255次)來控制嵌入函數(shù)擴(kuò)展的發(fā)生次數(shù),這個編譯指示控制用inline,__inline標(biāo)記的或在/Ob2選項下能自動嵌入的嵌入函數(shù)。
inline_depth編譯指示控制能夠被擴(kuò)展的一系列函數(shù)調(diào)用。例如,如果嵌入深度是4,并且如果A調(diào)用B然后調(diào)用C,所有的3次調(diào)用都將做嵌入擴(kuò)展。然而,如果設(shè)置的最近一次嵌入深度是2,則只有A和B被擴(kuò)展,而C仍然作為函數(shù)調(diào)用。
為了使用這個編譯指示,你必須設(shè)置編譯程序選項/Ob為1或者2。用這個編譯指示指定的深度設(shè)定在該指示后面的第一個函數(shù)開始生效。如果你在括號內(nèi)不指定一個值,inline_depth設(shè)置嵌入深度到默認(rèn)值8。
在擴(kuò)展時,嵌入深度可以被減少而不能被增加。如果嵌入深度是6,同時在擴(kuò)展過程中預(yù)處理程序遇到一個inline_depth編譯指示設(shè)置為8,則深度保持為6。
嵌入深度0將拒絕嵌入擴(kuò)展,深度255將設(shè)置在嵌入擴(kuò)展時沒有限制。如果用一個沒有指定值的編譯指示,則使用為默認(rèn)值。
15 inline_recursion
#pragma inline_recursion( [{on | off}] )控制直接或者相互間的遞歸函數(shù)調(diào)用式的嵌入擴(kuò)展。用這個編譯指示控制用inline,__inline標(biāo)記的或在/Ob2選項下能自動嵌入的嵌入函數(shù)。使用這個編譯指示需要設(shè)置編譯程序選項/Ob為1或者2。默認(rèn)的inline_recursion狀態(tài)是off。這個編譯指示在出現(xiàn)該編譯指示之后第一個函數(shù)調(diào)用起作用,并不影響函數(shù)的定義。
inline_recursion編譯指示控制如何擴(kuò)展遞歸函數(shù)。如果inline_recursion是off,并且如果一個嵌入函數(shù)調(diào)用了它自己(直接的或者間接的),函數(shù)將僅僅擴(kuò)展一次。如果inline_recursion是on,函數(shù)將擴(kuò)展多次直到達(dá)到inline_depth的值或者容量限制。
16 intrinsic
#pragma intrinsic( function1 [, function2, ...] )指定對在編譯指示參數(shù)表中函數(shù)調(diào)用是內(nèi)含的。編譯程序像嵌入代碼一樣生成內(nèi)含函數(shù),而不是函數(shù)調(diào)用。下面列出了具有內(nèi)含形式的庫函數(shù)。一旦遇到intrinsic編譯指示,它從第一個包含指定內(nèi)含函數(shù)的函數(shù)定義開始起作用。作用持續(xù)到源文件尾部或者出現(xiàn)包含相同內(nèi)含函數(shù)的function編譯指示。intrinsic編譯指示只能用在函數(shù)定義外——在全局層次。
下列函數(shù)具有內(nèi)含形式:
使用內(nèi)含函數(shù)的程序更快,因為它們沒有函數(shù)調(diào)用的額外代價,然而因為有附加的代碼生成,可能比較大。
注意,_alloca和setjmp函數(shù)總是內(nèi)含的,這個行為不受intrinsic編譯指示影響。
下列浮點函數(shù)沒有內(nèi)含形式。然而它們具有直接將參數(shù)通過浮點芯片傳送而不是推入程序堆棧的版本。
當(dāng)你同時指定/Oi和/Og編譯程序選項(或者任何包含/Og,/Ox,/O1和/O2的選項)時下列浮點函數(shù)具有真正的內(nèi)含形式。
你可以用編譯程序選項/Op或/Za來覆蓋真內(nèi)含浮點選項的生成。在這種情況下,函數(shù)會像一般庫函數(shù)一樣被生成,同時直接將參數(shù)通過浮點芯片傳送而不是推入程序堆棧。
17 message
#pragma message( messagestring )不中斷編譯,發(fā)送一個字符串文字量到標(biāo)準(zhǔn)輸出。message編譯指示的典型運(yùn)用是在編譯時顯示信息。
下面的代碼段用message編譯指示在編譯過程中顯示一條信息:
#if _M_IX86 == 500
#pragma message( "Pentium processor build" )
#endif
messagestring參數(shù)可以是一個能夠擴(kuò)展成字符串文字量的宏,并且你能夠用字符串文字量和宏的任何組合來構(gòu)造。例如,下面的語句顯示被編譯文件的文件名和文件最后一次修改的日期和時間。
#pragma message( "Compiling " __FILE__ )
#pragma message( "Last modified on " __TIMESTAMP__ )
18 once
#pragma once指定在創(chuàng)建過程中該編譯指示所在的文件僅僅被編譯程序包含(打開)一次。該編譯指示的一種常見用法如下:
//header.h
#pragma once
// Your C or C++ code would follow:
19 optimize
僅在專業(yè)版和企業(yè)版中存在 #pragma optimize( "[optimization-list]", {on | off} )代碼優(yōu)化僅有Visual C++專業(yè)版和企業(yè)版支持。詳見Visual C++ Edition。
指定在函數(shù)層次執(zhí)行的優(yōu)化。optimize編譯選項必須在函數(shù)外出現(xiàn),并且在該編譯指示出現(xiàn)以后的第一個函數(shù)定義開始起作用。on和off參數(shù)打開或關(guān)閉在optimization-list指定的選項。
optimization-list能夠是0或更多個在表2.2中給出的參數(shù):
表 2.2?? optimize編譯指示的參數(shù)
參數(shù) |
優(yōu)化類型 |
a |
假定沒有別名。 |
g |
允許全局優(yōu)化。 |
p |
增強(qiáng)浮點一致性。 |
s 或?t |
指定更短或者更快的機(jī)器代碼序列。 |
w |
假定在函數(shù)調(diào)用中沒有別名。 |
y |
在程序堆棧中生成框架指針。 |
這些和在/O編譯程序選項中使用的是相同的字母。例如:
#pragma optimize( "atp", on )
用空字符串("")的optimize編譯指示是一種特別形式。它要么關(guān)閉所有的優(yōu)化選項,要么恢復(fù)它們到原始(或默認(rèn))的設(shè)定。
#pragma optimize( "", off )
#pragma optimize( "", on )
20 pack
#pragma pack( [ n] )指定結(jié)構(gòu)和聯(lián)合成員的緊縮對齊。盡管用/Zp選項設(shè)定整個翻譯單元的結(jié)構(gòu)和聯(lián)合成員的緊縮對齊,可以用pack編譯指示在數(shù)據(jù)說明層次設(shè)定緊縮對齊。從出現(xiàn)該編譯指示后的第一個結(jié)構(gòu)或者聯(lián)合說明開始生效。這個編譯指示不影響定義。
當(dāng)你使用#pragma pack(n),其中n是1,2,4,8或者16,第一個以后的每個結(jié)構(gòu)成員保存在較小的成員類型或者n字節(jié)邊界上。如果你使用沒有參數(shù)的#pragma pack,結(jié)構(gòu)成員將被緊縮到由/Zp指定的值。默認(rèn)的/Zp緊縮的大小是/Zp8。
編譯程序還支持下面的增強(qiáng)語法:
#pragma pack( [ [ { push | pop}, ] [ identifier, ] ] [ n ] )
該語法允許你將使用不同緊縮編譯指示的組件合并到同一個翻譯單元內(nèi)。
每次出現(xiàn)有push參數(shù)的pack編譯指示將保存當(dāng)前的緊縮對齊值到一個內(nèi)部的編譯程序堆棧。編譯指示的參數(shù)列表從左向右讀取。如果你使用了push,當(dāng)前緊縮值被保存。如果你提供了一個n值,這個值將成為新的緊縮值。如果你指定了一個你選定的標(biāo)示符,這個標(biāo)示符將和新的緊縮值關(guān)聯(lián)。
每次出現(xiàn)有pop參數(shù)的pack編譯指示從內(nèi)部編譯程序堆棧頂部取出一個值并將那個值作為新的緊縮對齊。如果你用了pop,而內(nèi)部編譯程序堆棧是空的,對齊值將從命令行得到,同時給出一個警告。如果你用了pop并指定了n的值,那個值將成為新的緊縮值。如果你用了pop并指定了一個標(biāo)示符,將移去所有保存在堆棧中的的值直到匹配的找到匹配的標(biāo)示符,和該標(biāo)示符關(guān)聯(lián)的緊縮值也被從堆棧中移出來成為新的緊縮值。如果沒有找到匹配的標(biāo)示符,將從命令行獲取緊縮值并產(chǎn)生一個1級警告。默認(rèn)的緊縮對齊是8。
pack編譯指示的新的增強(qiáng)功能允許你編寫頭文件保證在使用頭文件之前和其后的緊縮值是一樣的:
/* File name: include1.h
*/
#pragma pack( push, enter_include1 )
/* Your include-file code ... */
#pragma pack( pop, enter_include1 )
/* End of include1.h */
在前面的例子中,進(jìn)入頭文件時將當(dāng)前緊縮值和標(biāo)示符enter_include1關(guān)聯(lián)并推入,被記住。在頭文件尾部的pack編譯選項移去所有在頭文件中可能遇到的緊縮值并移去和enter_include1關(guān)聯(lián)的緊縮值。這樣頭文件保證了在使用頭文件之前和其后的緊縮值是一樣的。
新功能也允許你在你的代碼內(nèi)用pack編譯指示為不同的代碼,例如頭文件設(shè)定不同的緊縮對齊。
#pragma pack( push, before_include1 )
#include "include1.h"
#pragma pack( pop, before_include1 )
在上一個例子中,你的代碼受到保護(hù),防止了在include.h中的任何緊縮值的改變。
21 pointers_to_members
C++特有 #pragma pointers_to_members(pointer-declaration, [most-general-representation] )指定是否能夠在相關(guān)類定義之前說明一個指向類成員的指針,并且用于控制指針的大小和解釋指針的代碼。你能夠在你的源代碼中使用pointers_to_members編譯知識來代替/vmx編譯程序選項。
pointer-declaration參數(shù)指出是否在相關(guān)函數(shù)定義之前或其后你已經(jīng)說明了一個指向成員的指針。pointer-declaration參數(shù)是下面兩個符號之一:
參數(shù) |
說明 |
full_generality | 生成安全的,但是有時不能優(yōu)化的代碼。如果有一些指向成員的指針在相關(guān)類定義之前說明,你要用full_generality。這個參數(shù)總是使用由most-general-representation指定的指針表示方式。 |
best_case | 對于所有指向成員的指針用最佳的表示方式生成安全的,優(yōu)化的代碼。需要在說明一個指向類成員指針之前定義類。默認(rèn)是best_case。 |
most-general-representaion參數(shù)指出在一個翻譯單元中編譯程序能夠安全引用任何指向類成員指針的最小指針表示方式。這個參數(shù)可以是下列之一:
參數(shù) | 說明 |
single_inheritance | 最普通的表示方式是單繼承,指向成員函數(shù)。如果用于指向具有多重或者虛擬繼承方式類成員的指針,將產(chǎn)生一個錯誤。 |
multi_inheritance | 最普通的表示方式是多重繼承,指向成員函數(shù)。如果用于指向具有虛擬繼承方式類成員的指針,將產(chǎn)生一個錯誤。 |
virtual_inheritance | 最普通的表示方式是虛擬繼承,指向成員函數(shù)。不會產(chǎn)生錯誤。當(dāng)使用#pragma pointers_to_members (full_generality)時這是默認(rèn)的參數(shù)。 |
22 setlocale
#pragma setlocale( "locale-string" )定義用于翻譯寬字符常數(shù)和字符串文字量時用的地區(qū)(國家和語言)。由于用于從多字節(jié)字符轉(zhuǎn)換到寬字符的算法根據(jù)地區(qū)或者由于在運(yùn)行可執(zhí)行程序不同的地方進(jìn)行編譯而不同,這個編譯指示提供一種在編譯時指定目標(biāo)地區(qū)的方式。這保證寬字符字符串將以正確的格式保存。默認(rèn)的locale-string是“C”。“C”地區(qū)將字符串中的每個字符作為wchar_t(即unsigned int)映射其值。
23 vtordisp
C++特有 #pragma vtordisp({on | off} )允許隱藏的附加vtordisp構(gòu)造函數(shù)/析構(gòu)函數(shù)替換成員。vtordisp編譯指示僅能夠用于具有虛擬基類的代碼。如果派生類從一個虛擬基類重載了一個虛擬函數(shù),并且如果派生類的構(gòu)造函數(shù)或析構(gòu)函數(shù)用指向虛擬基類的指針調(diào)用了這個函數(shù),編譯程序?qū)⒏鶕?jù)虛擬基類在類中引入一個附加的隱藏“vtordisp”域。
vtodisp編譯選項影響它后面的類布局。/vd0和/vd1選項為整個模塊指定了相同的行為。指定off將禁止隱藏的vtordisp成員,指定on(默認(rèn))將在它們需要的時候允許vtordisp。僅在不可能出現(xiàn)類的構(gòu)造函數(shù)和析構(gòu)函數(shù)通過this指針調(diào)用其指向?qū)ο笾械奶摂M函數(shù)時才關(guān)閉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 | 對指定信息應(yīng)用默認(rèn)的編譯程序選項。 |
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.
對于那些關(guān)于代碼生成的,大于4699的警告標(biāo)號,warning編譯指示僅在函數(shù)定義外時有效。如果指定的警告編號大于4699并且用于函數(shù)內(nèi)時被忽略。下面例子說明了用warning編譯指示禁止、然后恢復(fù)有關(guān)代碼生成警告信息的正確位置:
int a;
#pragma warning( disable : 4705 )
void func()
{
a;
}
#pragma warning( default : 4705 )
warning編譯指示也支持下面語法:
#pragma warning( push [ ,n ] )
#pragma warning( pop )
這里n表示警告等級(1到4)。
warning(push)編譯指示保存所有警告的當(dāng)前警告狀態(tài)。warning(push,n)保存所有警告的當(dāng)前狀態(tài)并將全局警告等級設(shè)置為n。
warning(pop)彈出最后一次推入堆棧中的警告狀態(tài)。任何在push和pop之間改變的警告狀態(tài)將被取消??紤]下面的例子:
#pragma warning( push )
#pragma warning( disable : 4705 )
#pragma warning( disable : 4706 )
#pragma warning( disable : 4707 )
// Some code
#pragma warning( pop )
在這些代碼的結(jié)束,pop恢復(fù)了所有警告的狀態(tài)(包括4705,4706和4707)到代碼開始時候的樣子。
當(dāng)你編寫頭文件時,你能用push和pop來保證任何用戶修改的警告狀態(tài)不會影響正常編譯你的頭文件。在頭文件開始的地方使用push,在結(jié)束地方使用pop。例如,假定你有一個不能順利在4級警告下編譯的頭文件,下面的代碼改變警告等級到3,然后在頭文件的結(jié)束時恢復(fù)到原來的警告等級。
#pragma warning( push, 3 )
// Declarations/ definitions
#pragma warning( pop )
英特爾工藝真的落后了嗎?
gcc和g++是什么,有什么區(qū)別?
TCP三次握手和四次揮手以及11種狀態(tài)
長按前往圖中包含的公眾號關(guān)注
免責(zé)聲明:本文內(nèi)容由21ic獲得授權(quán)后發(fā)布,版權(quán)歸原作者所有,本平臺僅提供信息存儲服務(wù)。文章僅代表作者個人觀點,不代表本平臺立場,如有問題,請聯(lián)系我們,謝謝!