C語言中#pragma預(yù)處理指令的使用
一. pragma預(yù)處理指令概念
在所有的預(yù)處理指令中,#pragma指令可能是最復(fù)雜的了,它的作用是設(shè)定編譯器的狀態(tài)或者是指示編譯器完成一些特定的動作。
二. pragma預(yù)處理指令的作用
#pragma指令對每個編譯器給出了一個方法,在保持與C和C++語言完全兼容的情況下,給出主機或操作系統(tǒng)專有的特征。依據(jù)定義,編譯指示是機器或操作系統(tǒng)專有的,且對于每個編譯器都是不同的。
#pragma為編譯器提供了一種在不同機器和操作系統(tǒng)上編譯以保持C和C++完全兼容的方法。
三. 預(yù)處理指令的參數(shù)
其格式一般為: #pragma para 其中para為參數(shù),下面來看一些常用的參數(shù)。
1)message參數(shù)
message參數(shù)是我最喜歡的一個參數(shù),它能夠在編譯信息輸出窗口中輸出相應(yīng)的信息,這對于源代碼信息的控制是非常重要的。其使用方法為:
#pragma message("HELLO WORLD")
message參數(shù)應(yīng)用
當(dāng)編譯器遇到這條指令時就在編譯輸出窗口中將消息文本打印出來。 當(dāng)我們在程序中定義了許多宏來控制源代碼版本的時候,我們自己有可能都會忘記有沒有正確的設(shè)置這些宏,此時我們可以用這條指令在編譯的時候就進(jìn)行檢查。假設(shè)我們希望判斷自己有沒有在源代碼的什么地方定義了_X86這個宏,可以用下面的方法:
#ifdef _X86 #pragma message("_X86 macro activated!") #endif
我們定義了_X86這個宏以后,應(yīng)用程序在編譯時就會在編譯輸出窗口里顯示X86 macro activated。我們就能夠記得自己定義的一些特定的宏了。
2)code_seg參數(shù)
它是另一個使用得比較多的pragma參數(shù),格式如:
#pragma code_seg( [ [ { push | pop}, ] [ identifier, ] ] [ "segment-name" [, "segment-class" ] )
它能夠設(shè)置程序中函數(shù)代碼存放的代碼段,當(dāng)我們開發(fā)驅(qū)動程序的時候就會使用到它。
push (可選參數(shù))將一個記錄放到內(nèi)部編譯器的堆棧中,可選參數(shù)可以為一個標(biāo)識符或者節(jié)名;
pop (可選參數(shù))將一個記錄從堆棧頂端彈出,該記錄可以為一個標(biāo)識符或者節(jié)名;
identifier (可選參數(shù))當(dāng)使用push指令時,為壓入堆棧的記錄指派的一個標(biāo)識符,當(dāng)該標(biāo)識符被刪除的時候和其相關(guān)的堆棧中的記錄將被彈出堆棧;
segment-name (可選參數(shù))表示函數(shù)存放的節(jié)名。
//默認(rèn)情況下,函數(shù)被存放在.text節(jié)中 void func1() { // stored in .text } //將函數(shù)存放在.my_data1節(jié)中 #pragma code_seg(".my_data1") void func2() { // stored in my_data1 } //r1為標(biāo)識符,將函數(shù)放入.my_data2節(jié)中 #pragma code_seg(push, r1, ".my_data2") void func3() { // stored in my_data2 } int main() { }
3)once參數(shù)
#pragma once 用于保證頭文件只被編譯一次
#pragma once也是編譯器相關(guān)的,不一定被支持
#pragma once的效率比使用#ifndef更高。
由于有些編譯器支持 #pragma once,有些不支持,怎么做既能保證高效又能保證多個編譯器之間可以通用呢,可以混合使用 #ifndef 和 #pragma once
4)pack參數(shù)
它就是用于指定內(nèi)存對齊方式。編譯器在默認(rèn)情況下按照 4 字節(jié)對齊,也就是說如果 #pragma pack() 不寫,則和 #pragma pack(4) 效果是相同的
這里是針對32位系統(tǒng),對于64位系統(tǒng)而言,默認(rèn)情況下按照8字節(jié)對齊。
許多實際的計算機系統(tǒng)對基本類型數(shù)據(jù)在內(nèi)存中存放的位置有限制,它們會要求這些數(shù)據(jù)的首地址的值是某個數(shù)k(通常它為4或8)的倍數(shù),這就是所謂的內(nèi)存對齊,而這個k則被稱為該數(shù)據(jù)類型的對齊模數(shù)(alignment modulus)。
Win32平臺下的微軟C編譯器(cl.exe for 80x86)在默認(rèn)情況下采用如下的對齊規(guī)則: 任何基本數(shù)據(jù)類型T的對齊模數(shù)就是T的大小,sizeof(T)。比如對于double類型(8字節(jié)),就要求該類型數(shù)據(jù)的地址總是8的倍數(shù),而char類型數(shù)據(jù)(1字節(jié))則可以從任何一個地址開始。
5) section指令參數(shù)
#pragma section指令可用于創(chuàng)建一個自定義分區(qū),可以將全局變量或者函數(shù)放在這個自定義分區(qū)內(nèi)部,實現(xiàn)各個模塊之間的數(shù)據(jù)共享。
對于GNU C/C++編譯器來說,直接使用__attribute__((section(“xxx”)))對變量或函數(shù)進(jìn)行修飾即可自動創(chuàng)建好分區(qū),將變量和函數(shù)放入對應(yīng)分區(qū)。而在windows 的VC編譯器下,必須結(jié)合#pragma section和__declspec(allocate(“xxx”))兩個指令才能實現(xiàn)該功能。
6)warning(…)參數(shù)
啟用編譯器警告消息的行為和選擇性修改,語法為:
#pragma warning( disable : 4507 34; once : 4385; error : 164 ) //這1行跟下面3行效果一樣 #pragma warning( disable : 4507 34 ) //不發(fā)出4507和34警告,即有4507和34警告時不顯示 #pragma warning( once : 4385 ) //4385警告信息只報告一次 #pragma warning( error : 164 ) //把164警告信息作為一個錯誤
warning( push )指令存儲每個警告的當(dāng)前警告狀態(tài)。
warning( push, n)指令存儲每個警告的當(dāng)前狀態(tài)并將全局警告級別設(shè)置為 n。warning( pop )指令 彈出推送到堆棧上的最后一個警告狀態(tài)。
在push和pop之間對警告狀態(tài)所做的任何更改都將被撤消。
當(dāng)你編寫頭文件時,你能用push和pop來保證任何用戶修改的警告狀態(tài)不會影響正常編譯你的頭文件。在頭文件開始的地方使用push,在結(jié)束地方使用pop。
在使用標(biāo)準(zhǔn)C++進(jìn)行編程的時候經(jīng)常會得到很多的警告信息,而這些警告信息都是不必要的提示,所以我們可以使用#pragma warning(disable:xxxx)來禁止該類型的警告。
7)comment參數(shù)
#pragma comment(comment-type [,“commentstring”])
該指令將一個注釋記錄放入一個對象文件或可執(zhí)行文件中。
comment-type 是一個預(yù)定義的標(biāo)識符(如下所述,一共5個),它指定了注釋記錄的類型。 可選 commentstring 是一個字符串,它提供了某些注釋類型的附加信息。 由于 commentstring 是一個字符串,因此它遵循有關(guān)轉(zhuǎn)義字符、嵌入的引號 (") 和串聯(lián)的字符串的所有規(guī)則。
8)其他pragma的參數(shù)
#pragma resource ".dfm"表示把.dfm文件中的資源加入工程。*.dfm中包括窗體外觀的定義。
#pragma hdrstop表示預(yù)編譯頭文件到此為止,后面的頭文件不進(jìn)行預(yù)編譯。
四. 預(yù)處理指令的總結(jié)
#pragma用于指示編譯器完成一些特定的動作
#pragma所定義的很多指示字是編譯器特有的(后面的參數(shù)決定)
#pragma在不同的編譯器間是不可移植的
預(yù)處理器將忽略它不認(rèn)識的#pragma指令
不同編譯器可能以不同的方式解釋同一條 #pragma指令
到此這篇關(guān)于C語言中#pragma預(yù)處理指令的使用的文章就介紹到這了,更多相關(guān)C語言 #pragma預(yù)處理內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Qt結(jié)合libqrencode生成二維碼的實現(xiàn)示例
本文主要介紹了Qt結(jié)合libqrencode生成二維碼的實現(xiàn)示例,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-01-01關(guān)于嘗試開發(fā)PHP的MYSQL擴展的使用
本篇文章小編將為大家介紹,關(guān)于嘗試開發(fā)PHP的MYSQL擴展的使用,需要的朋友可以參考一下2013-04-04詳解C++標(biāo)準(zhǔn)庫中處理正則表達(dá)式的類std::regex
std?是?C++?標(biāo)準(zhǔn)庫的命名空間,包含了大量標(biāo)準(zhǔn)的?C++?類、函數(shù)和對象,這些類和函數(shù)提供了廣泛的功能,包括輸入輸出、容器、算法、字符串處理等,這篇文章主要介紹了C++標(biāo)準(zhǔn)庫中提供的用于處理正則表達(dá)式的類std::regex,需要的朋友可以參考下2024-03-03OpenCV4 實現(xiàn)背景分離的詳細(xì)步驟(背景減法模型)
背景分離(BS)是一種通過使用靜態(tài)相機來生成前景掩碼(即包含屬于場景中的移動對象像素的二進(jìn)制圖像)的常用技術(shù),本文給大家介紹OpenCV4 實現(xiàn)背景分離的詳細(xì)步驟,需要的朋友可以參考下2021-09-09