pragma (Visual C++)
pragma是一個可用來動態調整編譯器編譯選項的指令(directive),依據編譯器而定,不同的編譯器會有所出入
作者介紹一些常用的,先列在此處
(1)#pragma comment( lib, "lib_name.lib" ) 
    =>指定目前程式所使用的library
(2)#pragma once
    =>
在編譯時,只編譯一次
(3)#pragma warning( disable : xxxx )
  
  =>編譯時,將編號xxxx的警告關掉
(4)#pragma warning( once : xxxx)
    =>xxxx
號警告僅報告一次
(5)#pragma warning( error : xxxx)
   =>xxxx號警告為一個錯誤
(6)#pragma message("Compile_Message")
    =>
編譯時,在編譯輸出框架(Output pane)中加入Compile_Message文字
(7)#pragma pack( show | [n] )
    =>
指定structunion及類別成員的alignment
 
現在開始一一仔細介紹
(1)#pragma comment( lib, "lib_name.lib" ) 
當你使用一個非編譯器提供的library時,需要讓知道這個library的路徑與指定這個library給編譯器
在告訴編譯器目前
library的路徑之後(Tools / Options... / Directories / Show directories for: ->Library files)
雖然已經告訴編譯器目前library這個檔案的路徑,但還需要一個動作
就是指定目前程式所使用的library,有兩個方法
    #pragma comment(lib,"lib_name.lib")
    選擇Project->settings->link ->object/library modules 裡加入所指定或所需要的library
 
(2)#pragma once
一般在標題檔中加入,目的是在編譯時只編譯此檔案一次

//header.h
#pragma once
// Your C or C++ code would follow:

那與下列這樣的方式有什麼不同呢?
 

//header.h
#ifndef HEADER_NAME_H_
#define HEADER_NAME_H_
// Your C or C++ code would follow:
#endif

#pragma#ifndef,#define,#endif都是preprocessing directives
ISO/IEC 14882:1998(E)中第16章中有介紹,其中#pragma並沒有制定出一個共通的標準與使用格式
因為在每個編譯器中所制定出的#pragma格式可能不同,所以#pragma相對於#ifndef來說缺乏可攜式。
但如果只在VC的環境下寫程式時就不需要擔心了!
如果考慮到Portability的問題時,建議使用#ifndef,#define,#endif,否則使用那一個都沒有差別。
若對於Portability有興趣的話,可以參考這個網頁:C++ portability guide

(3)#pragma warning( disable : xxxx )
  
  =>編譯時,將編號xxxx的警告關掉
      =>意思是說當編譯時,碰到xxxx號警告時,將這個xxxx號警告濾除,不顯示出來
(4)#pragma warning( once : xxxx)
    =>xxxx
號警告僅報告一次
(5)#pragma warning( error : xxxx)
   =>xxxx號警告為一個錯誤
(6)#pragma message("Compile_Message")
    =>
編譯時,在編譯輸出框架(Output pane)中加入Compile_Message文字
 
(7)#pragma pack( show | [n] )
有一個strcut如下:
 

//sizeof(int) = 4 , sizeof(char) = 1 , sizeof(double) = 8 
struct Student
{
	char sex;
	unsigned int age;
	double average;	
};

int main()
{
	struct Student s1;
	cout<<(void *)&s1.sex<<endl		//0012FF70
	      <<(void *)&s1.age<<endl		//0012FF74
	      <<(void *)&s1.average<<endl;	//0012FF78
	cout<<sizeof(Student)<<endl;		//16

	return 0;
}

能判斷出這個Student struct的大小(size)嗎?是13對嗎?
但若在VC下計算時,不會得到13,因為這牽扯到struct alignment的問題
在許多機器上為了存取的效率,編譯器配置給8bytes變數的位址必須是8的倍數
,配置給4bytes變數的位址是4的倍數,因為如此,有時需空下幾個bytes的空間
來讓變數放置在存取效率較佳的位址上,而這個調整的動作稱為boundary alignment(邊界對齊)
或稱為struct alignment(結構對齊)也有人稱為data alignment(資料對齊)
注意到上面的程式,s1.age的位址了嗎?並不是0012FF71而是0012FF74,這就是alignment的關係
要如何做調整呢?可以利用#pragma pack


#pragma pack(push,1)	//將編譯器預設的alignment存入編譯器內部堆疊中,並設定alignment1
struct Student
{
	char sex;
	unsigned int age;
	double average;	
};
#pragma pack(pop)	//將置於編譯器內部堆疊頂端的值pop出來,並指定給alignment

(1)#pragma pack( push , n  )
這個動作有兩個,有先後動作
    Ⅰ
. 將目前packing alignment的值推入(push)編譯器內部堆疊(internal stack)
    Ⅱ
. 將目前的pack alignmentvalue設定成n

(2)
#pragma pack(pop)
將在編譯器內部堆疊(internal stack)頂端(top)的值設定給packing alignment

接著重新編譯之後,就會得到13!
介紹有幫助!



參考資料
(1)MSDN:Pragma Directives
(2)MSDN:Compiler Warnings That Are Off by Default
(3)Compiler Error Messages
(4)C++ portability guide

回目錄
Written By James On 2004/09/09 


Hosted by www.Geocities.ws

1