#pragma編譯指令大全(下)

接上一篇#pragma編譯指令大全(上)


inline_depth

語(yǔ)法

#pragma inline_depth( [n] ) 

作用

指定函數(shù)的內(nèi)斂深度,超過深度n的內(nèi)斂擴(kuò)展均轉(zhuǎn)為函數(shù)調(diào)用。

備注

  1. inline_depth的控制范圍是用inline,__inline標(biāo)記或在/Ob2編譯選項(xiàng)下能夠自動(dòng)內(nèi)斂的函數(shù)。
  2. n的取值范圍是[0,255], 0代表禁用內(nèi)斂,255表示不限制內(nèi)斂深度。未指定n值情況下默認(rèn)為254。
  3. inline_depth可以控制一些列函數(shù)調(diào)用的內(nèi)斂深度。舉例,假設(shè)內(nèi)斂深度是4,如果A調(diào)用B然后調(diào)用C,所有的3次調(diào)用都將做內(nèi)斂擴(kuò)展。然而,如果設(shè)置的最近一次內(nèi)斂深度是2,則只有A和B被擴(kuò)展,而C仍然作為函數(shù)調(diào)用。
  4. 要使用該指令,必須設(shè)置編譯選項(xiàng)為/Ob1或/Ob2,并且在該指令設(shè)定內(nèi)斂深度后的第一個(gè)函數(shù)生效。
  5. 嵌套的內(nèi)斂深度設(shè)置只能遞減,不能遞增。如果內(nèi)斂深度為6,同時(shí)后續(xù)通過inline_depth編譯指令設(shè)置為8,則內(nèi)斂深度仍保持為6。
  6. inline_depth對(duì)使用__forceinline標(biāo)記的函數(shù)無效。

遞歸函數(shù)的內(nèi)斂深度為16。


inline_recursion

語(yǔ)法

#pragma inline_recursion( [{on | off}] )

作用

控制直接或間接遞歸調(diào)用函數(shù)的內(nèi)斂展開。

備注

  1. inline_recursion的控制范圍是用inline,__inline標(biāo)記或在/Ob2編譯選項(xiàng)下能夠自動(dòng)內(nèi)斂的函數(shù)。
  2. 要使用該指令,必須設(shè)置編譯選項(xiàng)為/Ob1或/Ob2,并且在該指令設(shè)定開關(guān)后的第一個(gè)函數(shù)生效。
  3. 默認(rèn)情況下開關(guān)為off。
  4. 如果開關(guān)為off,且內(nèi)斂函數(shù)調(diào)用自身,則該函數(shù)只展開一次。
  5. 如果開關(guān)為on,則該函數(shù)將展開多次,直至達(dá)到使用inline_depth設(shè)定的內(nèi)斂深度。

intrinsic

語(yǔ)法

#pragma intrinsic( function1 [, function2, ...] )

作用

指定參數(shù)列表中的函數(shù)為內(nèi)建函數(shù)。

備注

  1. intrinsic告訴編譯器函數(shù)行為明確,如果性能更好的情況下可以直接調(diào)用函數(shù)而無需采用內(nèi)斂展開。
  2. 在intrinsic指令出現(xiàn)之后的第一個(gè)包含內(nèi)建函數(shù)的函數(shù)定義開始生效。作用效果持續(xù)到源文件末尾或者遇到funtion編譯指令指定相同的函數(shù)。
  3. intrinsic只能在函數(shù)定義外使用-在全局層次。
  4. 下面是具有內(nèi)建形式的庫(kù)函數(shù)。
row1 row2 row3
_disable _outp fabs
_enable _outpw labs
_inp _rotl memcmp
_inpw _rotr memcpy
_lrotl _strset memset
_lrotr abs strcat
strcmp strcpy strlen

*5. 使用intrinsic函數(shù)的程序之所以運(yùn)行速度更快,是因?yàn)樗鼪]有函數(shù)調(diào)用的開銷,但是由于插入了額外的代碼,所以程序會(huì)更大。

*6. 下列的浮點(diǎn)數(shù)函數(shù)不具有真正的intrinsic形式,它們可以直接將浮點(diǎn)參數(shù)傳到浮點(diǎn)芯片中,而不是將參數(shù)壓入程序堆棧。

row1 row2 row3 row4
acos cosh pow tanh
asin fmod sinh

*7. 當(dāng)指定編譯選項(xiàng)/Oi/Og/fp:fast(或任何包含/Og的選項(xiàng):/Ox/O1和/O2)時(shí),下面列出的浮點(diǎn)函數(shù)將具有真正的intrinsic形式。

row1 row2 row3 row4
atan exp log10 sqrt
atan2 log sin tan
cos

示例代碼

// pragma_directive_intrinsic.cpp  
// processor: x86  
#include <dos.h>   // definitions for _disable, _enable  
#pragma intrinsic(_disable)  
#pragma intrinsic(_enable)  
void f1(void) {  
   _disable();  
   // do some work here that should not be interrupted  
   _enable();  
}  
int main() {  
}  

loop

語(yǔ)法

#pragma loop( hint_parallel(n) )
#pragma loop( no_vector )
#pragma loop( ivdep )

作用

控制對(duì)循環(huán)代碼的自動(dòng)并行化和自動(dòng)向量化

備注

  1. hint_parallel(n): 提示編譯器對(duì)循環(huán)代碼進(jìn)行n線程并行。n為0時(shí)采用最大數(shù)量的線程。該指令只是一個(gè)提示,并不是命令,編譯器不能保證將循環(huán)并行化。
  2. 如果循環(huán)具有數(shù)據(jù)依賴或結(jié)構(gòu)化問題,比如循環(huán)存儲(chǔ)了循環(huán)體外的標(biāo)量,將不會(huì)并行化。
  3. 只有指定/Qpar編譯選項(xiàng)時(shí),hint_parallel才會(huì)生效。
  4. no_vector:默認(rèn)情況下,自動(dòng)向量化時(shí)打開的。
  5. idevp:提示編譯器忽略該循環(huán)的向量依賴。
  6. loop編譯指令需要放在緊挨著循環(huán)體之前,不能放在循環(huán)體內(nèi),并且對(duì)接下來的循環(huán)生效。
  7. 可以對(duì)同一個(gè)循環(huán)體指定多個(gè)loop選項(xiàng),但是每個(gè)選項(xiàng)都要使用單獨(dú)一條指令。

make_public

語(yǔ)法

#pragma make_public(type)

作用

指示本機(jī)類型應(yīng)具有公共程序集可訪問性。

備注

  1. type: 需要具有公共程序集可訪問性的類型名稱。
  2. 如果要引用的本機(jī)類型來自無法更改的.h文件,則 make_public 會(huì)很有用。
  3. 若要在帶有公共程序集可見性的類型中使用公共函數(shù)簽名中的本機(jī)類型,則本機(jī)類型還必須具有公共程序集可訪問性,否則編譯器將發(fā)出警告。
  4. make_public必須在全局范圍內(nèi)使用,并且僅在編譯指令指定處到源文件末尾有效。
  5. 可以隱式或顯式將本機(jī)類型設(shè)為私有;詳細(xì)信息請(qǐng)參閱類型可見性

示例代碼

// make_public_pragma.h  
struct Native_Struct_1 { int i; };  
struct Native_Struct_2 { int i; };

// make_public_pragma.cpp  
// compile with: /c /clr /W1  
#pragma warning (default : 4692)  
#include "make_public_pragma.h"  
#pragma make_public(Native_Struct_1)  
  
public ref struct A {  
   void Test(Native_Struct_1 u) {u.i = 0;}   // OK  
   void Test(Native_Struct_2 u) {u.i = 0;}   // C4692  
}; 

注意上述代碼示例指定的編譯選項(xiàng):/c /clr /W1


managed, unmanaged

語(yǔ)法

#pragma managed  
#pragma unmanaged  
#pragma managed([push,] on | off)  
#pragma managed(pop)  

作用

啟用函數(shù)級(jí)控制以將函數(shù)編譯為托管或未托管函數(shù)。

備注

  1. /clr編譯器選項(xiàng)提供了用于將函數(shù)編譯為托管或非托管函數(shù)的模塊級(jí)控制。
  2. 非托管函數(shù)將在本機(jī)平臺(tái)編譯成機(jī)器碼,并且由CLR傳給本機(jī)平臺(tái)運(yùn)行。
  3. 啟用/clr編譯選項(xiàng)后,默認(rèn)情況下將函數(shù)編譯為托管函數(shù)。
  4. 該編譯指令需要放在函數(shù)體之前,不能放在函數(shù)體內(nèi)。
  5. 該編譯指令必須放在#include指令之后。
  6. 如果未設(shè)定/clr編譯選項(xiàng),編譯器將忽略managed和unmanaged編譯指令。
  7. 該編譯指令可以在模板函數(shù)實(shí)例化之后確定該函數(shù)是否為托管函數(shù)。
  8. 更多詳細(xì)信息請(qǐng)參閱混合程序集的初始化;

示例代碼

// pragma_directives_managed_unmanaged.cpp  
// compile with: /clr  
#include <stdio.h>  
  
// func1 is managed  
void func1() {  
   System::Console::WriteLine("In managed function.");  
}  
  
// #pragma unmanaged  
// push managed state on to stack and set unmanaged state  
#pragma managed(push, off)  
  
// func2 is unmanaged  
void func2() {  
   printf("In unmanaged function.\n");  
}  
  
// #pragma managed  
#pragma managed(pop)  
  
// main is managed  
int main() {  
   func1();  
   func2();  
}

In managed function.
In unmanaged function.


message

語(yǔ)法

#pragma message( messagestring )

作用

在不中斷編譯的情況下將字符串輸出到標(biāo)準(zhǔn)輸出窗口。

備注

  1. 該編譯指令的典型用法是輸出信息性消息。
  2. messagestring可以是宏,也可以是字符串和宏的拼接。
  3. 在該編譯指令中使用的宏應(yīng)該返回字符串類型,否則需要主動(dòng)將宏返回信息轉(zhuǎn)換成字符串類型。

示例代碼

// pragma_directives_message1.cpp  
// compile with: /LD  
#if _M_IX86 >= 500  
#pragma message("_M_IX86 >= 500")  
#endif  
  
#pragma message("")  
  
#pragma message( "Compiling " __FILE__ )   
#pragma message( "Last modified on " __TIMESTAMP__ )  
  
#pragma message("")  
  
// with line number  
#define STRING2(x) #x  
#define STRING(x) STRING2(x)  
  
#pragma message (__FILE__ "[" STRING(__LINE__) "]: test")  
  
#pragma message("")

omp

語(yǔ)法

#pragma omp directive

作用

將一個(gè)或多個(gè)OpenMP指令與任何可選指令子集一起使用。


once

語(yǔ)法

#pragma once

作用

指定該文件在編譯源文件時(shí)僅被編譯器包含(打開)一次。

備注

  1. 該編譯指令可以減少編譯次數(shù),通常被稱為多次包含優(yōu)化(multiple-include optimization)。
  2. 效果類似于#include guard idiom,后者通常采用預(yù)處理宏來防止多次包含同一文件。
  3. 該編譯指令還有助于避免違反單一定義原則(要求所有模板、類型、函數(shù)和對(duì)象在代碼中的定義不得超過一個(gè))。
  4. 如果要將代碼移植到不支持該編譯指令的編譯器平臺(tái),則建議使用#include guard idiom

示例代碼

// header.h  
#pragma once  
// Code placed here is included only once per translation unit

// header.h  
// Demonstration of the #include guard idiom.  
// Note that the defined symbol can be arbitrary.  
#ifndef HEADER_H_     // equivalently, #if !defined HEADER_H_  
#define HEADER_H_  
// Code placed here is included only once per translation unit  
#endif // HEADER_H_ 

optimize

語(yǔ)法

#pragma optimize( "[optimization-list]", {on | off} )

作用

指定編譯器對(duì)函數(shù)的優(yōu)化類型。

備注

  1. 該編譯指令必須放在函數(shù)體外部,并且對(duì)該指令設(shè)定后的函數(shù)生效。
  2. on和off用于打開或關(guān)閉optimization-list指定的優(yōu)化類型。
  3. optimization-list可以是下表中顯示的0個(gè)或多個(gè)參數(shù),與/O編譯選項(xiàng)參數(shù)一樣。
Parameter(s) Type of optimization
g Enable global optimizations.
s or t Specify short or fast sequences of machine code.
y Generate frame pointers on the program stack.
  1. 指令特殊形式:optimization-list為""空字符串。

示例代碼

// 等價(jià)于/Os編譯選項(xiàng)
#pragma optimize( "ts", on )

// 關(guān)閉前面指定的優(yōu)化選項(xiàng)
#pragma optimize( "", off )  
.  
.  
.
// 重新打開編譯優(yōu)化選項(xiàng)
#pragma optimize( "", on )

pack

語(yǔ)法

#pragma pack( [ show ] | [ push | pop ] [, identifier ] , n  )

作用

指定結(jié)構(gòu)、聯(lián)合和類成員的對(duì)齊方式。

備注

  1. 緊湊壓縮一個(gè)類就是將類成員變量在內(nèi)存中緊挨著存放,也就是說某些成員變量的對(duì)齊邊界比該變量類型的默認(rèn)情況要小。比如UINT64類型默認(rèn)情況是8字節(jié)對(duì)齊的,通過pack指令可以指定為4字節(jié)對(duì)齊。
  2. pack指令提供了數(shù)據(jù)聲明級(jí)別的控制,而/Zp編譯提供了模塊級(jí)別的控制。
  3. pack指令對(duì)設(shè)定之后的第一個(gè)struct,union或者class聲明生效,該指令對(duì)定義無效。
  4. 不帶參數(shù)的pack指令默認(rèn)將/Zp設(shè)置的對(duì)齊字節(jié)數(shù)作為n參數(shù)。當(dāng)/Zp未設(shè)定時(shí),默認(rèn)8字節(jié)對(duì)齊。
  5. 修改數(shù)據(jù)結(jié)構(gòu)的對(duì)齊方式之后,可以減少內(nèi)存的使用,但可能會(huì)降低性能或由于未對(duì)齊訪問引起硬件異常,可以通過SetErrorMode來修改異常行為模式。
  6. show: 可選參數(shù),通過警告消息顯示當(dāng)前的對(duì)齊方式。
  7. push: 可選參數(shù),將當(dāng)前對(duì)齊方式壓入編譯堆棧,設(shè)置后續(xù)對(duì)齊方式為n,n未指定則采用當(dāng)前對(duì)齊方式。
  8. pop: 可選參數(shù),彈出編譯堆棧頂部的元素,如果n未設(shè)定,則將彈出的頂部元素作為新的對(duì)齊方式,否則對(duì)齊方式為n。例如:#pragma pack(pop, 16)。如果pop指令指定了identifer(如#pragma pack(pop, r1)),則彈出r1之前包括r1的所有元素,并將新的棧頂元素作為對(duì)齊方式。如果未找到identifer標(biāo)示符,則忽略該指令。
  9. identifer: 可選參數(shù),指定壓入堆棧或彈出堆棧的標(biāo)示符。
  10. n: 可選參數(shù),指定用于對(duì)齊的值,單位為字節(jié)。有效值是1、2、4、8和16。
  11. 更多對(duì)齊信息請(qǐng)參閱__alignofalign__unalignedExamples of Structure Alignment

示例代碼

// pragma_directives_pack.cpp  
#include <stddef.h>  
#include <stdio.h>  
  
struct S {  
   int i;   // size 4  
   short j;   // size 2  
   double k;   // size 8  
};  
  
#pragma pack(2)  
struct T {  
   int i;  
   short j;  
   double k;  
};  
  
int main() {  
   printf("%zu ", offsetof(S, i));  
   printf("%zu ", offsetof(S, j));  
   printf("%zu\n", offsetof(S, k));  
  
   printf("%zu ", offsetof(T, i));  
   printf("%zu ", offsetof(T, j));  
   printf("%zu\n", offsetof(T, k));  
} 

0 4 8
0 4 6

// pragma_directives_pack_2.cpp  
// compile with: /W1 /c  
#pragma pack()   // n defaults to 8; equivalent to /Zp8  
#pragma pack(show)   // warning C4810: value of pragma pack(show) == 8 
#pragma pack(4)   // n = 4  
#pragma pack(show)   // warning C4810: value of pragma pack(show) == 4  
#pragma pack(push, r1, 16)   // n = 16, pushed to stack  
#pragma pack(show)   // warning C4810: value of pragma pack(show) == 16  
#pragma pack(pop, r1, 2)   // n = 2 , stack popped  
#pragma pack(show)   // warning C4810: value of pragma pack(show) == 2

pointers_to_members

語(yǔ)法

#pragma pointers_to_members( pointer-declaration, [most-general-representation] )

作用

指定能否在類定義之前聲明指向類成員的指針,以及類成員是否控制指針大小以及如何解析類成員指針。

備注

  1. 該編譯指令功能等價(jià)于/vmx編譯選項(xiàng)或繼承關(guān)鍵字
  2. pointer-declaration: 指定在關(guān)聯(lián)的函數(shù)定義之前還是之后聲明指向成員的指針。參數(shù)如下:
參數(shù) 注釋
full_generality 生成安全(有時(shí)并非最佳)代碼。如果在關(guān)聯(lián)的類定義之前聲明指向成員的任何指針,請(qǐng)使用full_generality。此參數(shù)始終使用most-general-representation參數(shù)所指定的指針表示形式。 等價(jià)于/vmg。
best_case 對(duì)指向成員的所有指針使用best-case representation參數(shù)生成安全的最佳代碼。 要求在聲明指向類成員的指針之前定義此類。 系統(tǒng)默認(rèn)為best_case。

*3. most-general-representation: 指定了最小指針表示形式,用于編譯器可以安全地引用指向編譯單元中的類成員的任何指針。參數(shù)如下:

參數(shù) 注釋
single_inheritance 最常見的表示形式為單一繼承(指向成員函數(shù)的指針)。如果類定義(已為其聲明指向成員的指針)的繼承模型為多重繼承或虛擬繼承,則會(huì)導(dǎo)致出現(xiàn)錯(cuò)誤。
multiple_inheritance 最常見的表示形式為多重繼承(指向成員函數(shù)的指針)。如果類定義(已為其聲明指向成員的指針)的繼承模型為虛擬繼承,則會(huì)導(dǎo)致出現(xiàn)錯(cuò)誤。
virtual_inheritance 最常見的表示形式為虛擬繼承(指向成員函數(shù)的指針)。不會(huì)導(dǎo)致錯(cuò)誤。這是#pragma pointers_to_members(full_generality)的默認(rèn)參數(shù)。

注意:建議將該編譯指令放在要使用的源文件中,并且放置在所有#include之后。避免影響其它源文件。

示例代碼

//   Specify single-inheritance only  
#pragma pointers_to_members( full_generality, single_inheritance )

pop_macro

語(yǔ)法

#pragma pop_macro( "macro_name" )

作用

將macro_name宏的值設(shè)置為堆棧頂部的存放該宏值。

備注

  1. 使用pop_macro之前必須先使用push_macro。

示例代碼

// pragma_directives_pop_macro.cpp  
// compile with: /W1  
#include <stdio.h>  
#define X 1  
#define Y 2  
  
int main() {  
   printf("%d",X);  
   printf("\n%d",Y);  
   #define Y 3   // C4005  
   #pragma push_macro("Y")  
   #pragma push_macro("X")  
   printf("\n%d",X);  
   #define X 2   // C4005  
   printf("\n%d",X);  
   #pragma pop_macro("X")  
   printf("\n%d",X);  
   #pragma pop_macro("Y")  
   printf("\n%d",Y);  
} 

1
2
1
2
1
3


push_macro

語(yǔ)法

#pragma push_macro(" macro_name ")

作用

將macro_name宏的值壓入堆棧頂端。

備注

  1. 可以通過pop_macro恢復(fù)macro_name宏的值。

示例代碼

請(qǐng)參閱上述pop_macro。


region, endregion

語(yǔ)法

#pragma region name
#pragma endregion comment

作用

利用#pragma region指定在使用Visual Studio的大綱功能時(shí)可展開或折疊的代碼塊。

備注

  1. comment: (可選參數(shù)),在代碼編輯器中顯示的注釋。
  2. name: (可選參數(shù)),區(qū)域名稱,此名稱將在代碼編輯器中顯示。
  3. #pragma endregion標(biāo)記#pragma region塊的結(jié)尾。兩者必須一起配合使用。

示例代碼

// pragma_directives_region.cpp  
#pragma region Region_1  
void Test() {}  
void Test2() {}  
void Test3() {}  
#pragma endregion Region_1  
  
int main() {} 

runtime_checks

語(yǔ)法

#pragma runtime_checks( "[runtime_checks]", {restore | off} )

作用

禁用或還原/RTC設(shè)置。

備注

  1. 在/RTC編譯選項(xiàng)未啟用時(shí)不能使用該編譯指令還原運(yùn)行時(shí)檢查。舉例:如果未指定/RTCs編譯選項(xiàng),則指定#pragma runtime_checks( "s", restore)也不會(huì)啟用堆棧幀校驗(yàn)。
  2. 該編譯指令必須放在函數(shù)體外部,而且在該指令之后的第一個(gè)函數(shù)定義開始生效。
  3. retore和off分別代表打開和關(guān)閉指定的runtime_checks。參數(shù)取值如下所示:
參數(shù) 運(yùn)行時(shí)檢查的類型
s 啟用堆棧(幀)校驗(yàn)。
c 提示某個(gè)數(shù)值向較小數(shù)據(jù)類型賦值時(shí)會(huì)導(dǎo)致數(shù)據(jù)丟失。
u 提示某個(gè)變量在定義之前被使用。

*4. 上表中的參數(shù)與/RTC編譯選項(xiàng)的參數(shù)相同,例如,#pragma runtime_checks( "sc", restore )

*5. 特殊形式:參數(shù)runtime_checks為空字符串(""),對(duì)應(yīng)功能如下:
a. off: 禁用上表中的運(yùn)行時(shí)錯(cuò)誤檢查。
b. restore: 重置運(yùn)行時(shí)錯(cuò)誤檢查為/RTC編譯選項(xiàng)中指定的類型。

示例代碼

#pragma runtime_checks( "", off ) 
.  
.  
.  
#pragma runtime_checks( "", restore )

更多信息請(qǐng)參閱:RTC Sample


section

語(yǔ)法

#pragma section( "section-name" [, attributes] )

作用

在obj文件中創(chuàng)建一個(gè)段。

備注

  1. 此處segment和section的概念是等價(jià)的。
  2. 一旦定義了一個(gè)段,將在編譯的剩余部分生效,但是必須通過__declspec(allocate)來指定段信息,否則將沒有數(shù)據(jù)存放在該段。
  3. section-name: 必須參數(shù),指定段名。該名不能與標(biāo)準(zhǔn)段名沖突。參見/SECTION查看不能使用的段名。
  4. attributes: 可選參數(shù),指定段屬性,各個(gè)屬性間用逗號(hào)分隔。可選屬性如下所示:
屬性 注釋
read 可讀
write 可寫
execute 可執(zhí)行
shared 共享
nopage 不可分頁(yè),對(duì)于win32設(shè)備驅(qū)動(dòng)程序很有用
nocahe 不可分頁(yè),對(duì)于win32設(shè)備驅(qū)動(dòng)程序很有用
discard 可丟棄,對(duì)于win32設(shè)備驅(qū)動(dòng)程序很有用
remove 非常駐內(nèi)存,僅適用于虛擬設(shè)備驅(qū)動(dòng)程序(VxD)。

示例代碼

// pragma_section.cpp  
#pragma section("mysec",read,write)  
int j = 0;  // 存放在數(shù)據(jù)段,因?yàn)闆]有使用__declspec(allocate)聲明
  
__declspec(allocate("mysec"))  
int i = 0;  // 存放在mysec段
  
int main(){}

setlocale

語(yǔ)法

#pragma setlocale( "[locale-string]" )

作用

定義在轉(zhuǎn)換寬字符常量和字符串時(shí)使用的區(qū)域設(shè)置(國(guó)家/地區(qū)和語(yǔ)言)。

備注

  1. 由于編譯可能在不同的區(qū)域設(shè)置環(huán)境下進(jìn)行,而不同區(qū)域?qū)⒍嘧止?jié)轉(zhuǎn)換為寬字符的算法可能存在差異,因此可以使用setlocale來指定編譯時(shí)的區(qū)域設(shè)置。這樣可以保證寬字符能夠以正確的格式保存。
  2. locale-string的默認(rèn)值是""
  3. "C"區(qū)域設(shè)置會(huì)將字符串中的每個(gè)字符作為wchar_t(unsigned short)映射到"C"區(qū)域設(shè)置的值。
  4. 其它有效的參數(shù)是語(yǔ)言字符串列表中的區(qū)域選項(xiàng)。

示例代碼

#pragma setlocale("dutch")

能否處理指定的語(yǔ)言字符串取決于計(jì)算機(jī)是否支持對(duì)應(yīng)的代碼頁(yè)(code page)和語(yǔ)言ID。


strict_gs_check

語(yǔ)法

#pragma strict_gs_check([push,] on )   
#pragma strict_gs_check([push,] off )   
#pragma strict_gs_check(pop)

作用

提供加強(qiáng)型的安全檢測(cè)。

備注

  1. 指示編譯器在函數(shù)堆棧中插入隨機(jī)Cookie以便于檢測(cè)某些類別的基于堆棧的緩沖區(qū)溢出。
  2. 默認(rèn)情況下,/GS(緩沖區(qū)安全檢查)編譯選項(xiàng)不會(huì)為所有函數(shù)插入Cookie進(jìn)行檢測(cè)。更多詳細(xì)信息請(qǐng)參閱/GS(緩沖區(qū)安全檢查)
  3. 必須啟動(dòng)/GS編譯選項(xiàng)后才能使用strict_gs_check編譯指令。
  4. 該編譯指令一般用于存在潛在危害的數(shù)據(jù)的代碼模塊。
  5. 該編譯指令的攻擊性較強(qiáng),可以應(yīng)用于可能不需要保護(hù)的函數(shù),但是為了盡可能降低對(duì)應(yīng)用程序的影響,它通常會(huì)進(jìn)行優(yōu)化。
  6. 即使使用了該編譯指令,也要盡可能編寫安全的代碼,確保代碼中不存在緩沖區(qū)溢出。

示例代碼

// pragma_strict_gs_check.cpp  
// compile with: /c  
  
#pragma strict_gs_check(on)  
  
void ** ReverseArray(void **pData,  
                     size_t cData)  
{  
    // *** This buffer is subject to being overrun!! ***  
    void *pReversed[20];  
  
    // Reverse the array into a temporary buffer  
    for (size_t j = 0, i = cData; i ; --i, ++j)  
        // *** Possible buffer overrun!! ***  
            pReversed[j] = pData[i];   
  
    // Copy temporary buffer back into input/output buffer  
    for (size_t i = 0; i < cData ; ++i)   
        pData[i] = pReversed[i];  
  
    return pData;  
}

vtordisp

語(yǔ)法

#pragma vtordisp([push,] n)  
#pragma vtordisp(pop)  
#pragma vtordisp()  
#pragma vtordisp([push,] {on | off})

作用

控制構(gòu)造/析構(gòu)偏移成員是否包含vtordisp隱藏字段。

備注

  1. push: 將當(dāng)前的vtordisp設(shè)置值壓入內(nèi)部編譯堆棧,并將新的vtordisp設(shè)置為n。如果未指定n的值,則不改變vtordisp的設(shè)置。
  2. pop: 將內(nèi)部編譯堆棧頂?shù)脑貜棾觯⑵湓O(shè)置為新的vtordisp設(shè)置。
  3. n: 指定vtordisp設(shè)置的值。可以是0,1或2,分別對(duì)應(yīng)于/vd0,/vd1和/vd2三個(gè)編譯選項(xiàng)。更多信息請(qǐng)參閱/vd(禁用構(gòu)造偏移)
  4. on: 等價(jià)于#pragma vtordisp(1)
  5. off: 等價(jià)于#pragma vtordisp(0)
  6. 該編譯指令只能用于具有虛擬基類的代碼。產(chǎn)生vtordisp的條件如下:
    a. 虛繼承中派生類重寫了基類的虛函數(shù)。
    b. 派生類在構(gòu)造函數(shù)或析構(gòu)函數(shù)中通過虛基類的指針調(diào)用了重寫的基類函數(shù)。
  7. 該編譯指令會(huì)影響它之后類的對(duì)象模型。功能等價(jià)于/vd0,/vd1和/vd2編譯選項(xiàng),但是作用范圍不同。編譯選項(xiàng)作用于整個(gè)模塊,編譯指令的作用范圍根據(jù)設(shè)置的打開與關(guān)閉相關(guān)。
  8. 默認(rèn)設(shè)置為on(1),在必要時(shí)啟用vtordisp字段。
  9. 設(shè)置為2時(shí)將對(duì)所有具有虛函數(shù)的虛基類啟用vtordisp字段。
  10. vtordisp(2)可以確保dynamic_cast在部分構(gòu)造的對(duì)象上正常工作。更多信息請(qǐng)參閱編譯器警告(等級(jí) 1)C4436
#pragma vtordisp(push, 2)  
class GetReal : virtual public VBase { ... };  
#pragma vtordisp(pop)

warning

語(yǔ)法

#pragma warning(   
      warning-specifier  
       :   
      warning-number-list [; warning-specifier : warning-number-list...] )  
#pragma warning( push[ ,n ] )  
#pragma warning( pop )

作用

選擇性修改編譯警告消息行為。

備注

  1. warning-specifier: 警告描述符,同一編譯指令中可以指定多個(gè),有效參數(shù)如下所示。
警告描述符 注釋
1, 2, 3, 4 指定警告級(jí)別。 同時(shí)會(huì)啟用默認(rèn)情況下處于關(guān)閉狀態(tài)的指定警告。
default 重置警告級(jí)別為默認(rèn)值。 同時(shí)會(huì)啟用默認(rèn)情況下處于關(guān)閉狀態(tài)的指定警告。 警告將在其默認(rèn)存檔級(jí)別生成。有關(guān)詳細(xì)信息,請(qǐng)參閱默認(rèn)關(guān)閉的編譯器警告
disable 禁用指定的警告。
error 將指定警告報(bào)告為錯(cuò)誤。
once 只顯示一次指定的警告消息。
suppress 將當(dāng)前警告設(shè)置壓入堆棧,禁用下一行的指定警告,然后彈出警告堆棧,重置警告設(shè)置。

*2. warning-number-list: 參數(shù)可包含多個(gè)警告編號(hào)。

// 簡(jiǎn)寫
#pragma warning( disable : 4507 34; once : 4385; error : 164 )
// 等價(jià)于下面指令
// Disable warning messages 4507 and 4034.  
#pragma warning( disable : 4507 34 )  
// Issue warning 4385 only once.  
#pragma warning( once : 4385 )  
// Report warning 4164 as an error.  
#pragma warning( error : 164 ) 

*3. 編譯器會(huì)將0-999區(qū)間的告警編號(hào)默認(rèn)加上4000,變成4000-4999。

*4. 在函數(shù)左大括號(hào)已經(jīng)生效的警告狀態(tài)在函數(shù)體其余部分也生效。

*5. 4700-4900區(qū)間內(nèi)的警告與代碼生成相關(guān),使用warning編譯指令修改大于4699的警告狀態(tài)會(huì)在函數(shù)體末尾之后生效。

// pragma_warning.cpp  
// compile with: /W1  
#pragma warning(disable:4700)  
void Test() {  
   int x;  
   int y = x;   // no C4700 here  
   #pragma warning(default:4700)   // C4700 enabled after Test ends  
}  
  
int main() {  
   int x;  
   int y = x;   // C4700  
} 

函數(shù)體中只有最后一個(gè)warning編譯指令會(huì)在函數(shù)體末尾生效。

*6. push: 保存每個(gè)警告的當(dāng)前警告狀態(tài)并壓入編譯棧,設(shè)置警告級(jí)別為n。

*7. pop:彈出壓入編譯棧的最后一個(gè)警告狀態(tài),同時(shí)撤銷push和pop之間的所有修改,還原每個(gè)警告的狀態(tài)。

#pragma warning( push )  
#pragma warning( disable : 4705 )  
#pragma warning( disable : 4706 )  
#pragma warning( disable : 4707 )  
// Some code  
#pragma warning( pop ) 

pop會(huì)將每個(gè)警告(包括 4705、4706 和 4707)的狀態(tài)還原為其在代碼開頭的狀態(tài)。

*8. 編寫頭文件時(shí)可以使用push和pop來確保外部對(duì)警告狀態(tài)的修改不會(huì)影響到當(dāng)前文件。

#pragma warning( push, 3 )  
// Declarations/definitions  
#pragma warning( pop )

注意:要在文件開頭使用push,在文件末尾使用pop。

后記

終于總結(jié)完了,原來計(jì)劃是花幾天的晚上時(shí)間來整理就夠了,但是真正開始整理之后發(fā)現(xiàn)工作量遠(yuǎn)比預(yù)估的要大,斷斷續(xù)續(xù)差不多用了一周多時(shí)間,分析了一下主要的耗時(shí)有下面幾部分:

  1. 有些指令從來沒用過,需要查閱其它資料來熟悉和理解它。
  2. 理解MSDN的英文講解相對(duì)較容易,但是要把一些英文專業(yè)術(shù)語(yǔ)用中文表述出來卻需要反復(fù)斟酌一下,有種只可意會(huì),不可言傳的感覺,哈哈~
  3. 各個(gè)指令提供的示例代碼需要一些時(shí)間來調(diào)試和理解。

最后吐槽一下markdown的語(yǔ)法,一旦插入表格,后續(xù)的有序列表就會(huì)重新編號(hào),在網(wǎng)上看到好多人都遇到一樣的情況,最后用了*加數(shù)字的方式進(jìn)行處理,但是看著感覺還是有點(diǎn)怪怪的。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容