導航:首頁 > 源碼編譯 > 編譯搜索路徑優先順序

編譯搜索路徑優先順序

發布時間:2022-05-11 07:57:29

㈠ 關於C語言預處理命令

第一句有問題。
比如
#ifndef WIN32
#endif printf("OK\n");
在這里,這個printf就不會被執行。也就是說, 一行中, 只能有一條預處理指令,
編譯的預處理階段, 編譯器識別了一條完整的預處理指令後,後面的所有東西他都不要了。
對於第二句,在函數里,我們是可以使用預處理指令的。
比如
void fun(void)
{
#ifdef WIN32
... // 對於windows系統環境的操作
#else
... // 對於windows以外的系統環境的操作
#endif /* WIN32 */
...
}

樓上的同學, 你是在哪兒本書上看的? 介紹一下唄

㈡ matlab路徑優先順序 :是當前文件夾的路徑優先,還是setpath裡面的路徑優先

優先順序
當前文件>當前工作路徑>path路徑

先找當前文件中定義的函數,或者函數句柄
然後找當前工作目錄中的m文件
最後找set path中設定的路徑

㈢ #pragma的常用參數

Message 參數能夠在編譯信息輸出窗口中輸出相應的信息,這對於源代碼信息的控制是非常重要的。其使用方法為: #pragmamessage(消息文本)當編譯器遇到這條指令時就在編譯輸出窗口中將消息文本列印出來。
當我們在程序中定義了許多宏來控制源代碼版本的時候,我們自己有可能都會忘記有沒有正確的設置這些宏,此時我們可以用這條指令在編譯的時候就進行檢查。假設我們希望判斷自己有沒有在源代碼的什麼地方定義了_X86這個宏可以用下面的方法 #ifdef_X86#pragmamessage(_X86macroactivated!)#endif當我們定義了_X86這個宏以後,應用程序在編譯時就會在編譯輸出窗口裡顯示「_X86 macro activated! 」。我們就不會因為不記得自己定義的一些特定的宏而抓耳撓腮了。 (比較常用)
只要在頭文件的最開始加入這條指令就能夠保證頭文件被編譯一次,這條指令實際上在VC6中就已經有了,但是考慮到兼容性並沒有太多的使用它。
#pragma once是編譯相關,就是說這個編譯系統上能用,但在其他編譯系統不一定可以,也就是說移植性差,不過現在基本上已經是每個編譯器都有這個定義了。
#ifndef,#define,#endif這個是C++語言相關,這是C++語言中的宏定義,通過宏定義避免文件多次編譯。所以在所有支持C++語言的編譯器上都是有效的,如果寫的程序要跨平台,最好使用這種方式 #pragma hdrstop表示預編譯頭文件到此為止,後面的頭文件不進行預編譯。BCB可以預編譯頭文件以加快鏈接的速度,但如果所有頭文件都進行預編譯又可能占太多磁碟空間,所以使用這個選項排除一些頭文件。
有時單元之間有依賴關系,比如單元A依賴單元B,所以單元B要先於單元A編譯。你可以用#pragma startup指定編譯優先順序,如果使用了#pragma package(smart_init) ,BCB就會根據優先順序的大小先後編譯。 #pragmacomment(...)該指令將一個注釋記錄放入一個對象文件或可執行文件中。
常用的lib關鍵字,可以幫我們連入一個庫文件。
每個編譯程序可以用#pragma指令激活或終止該編譯程序支持的一些編譯功能。例如,對循環優化功能: #pragmaloop_opt(on)//激活#pragmaloop_opt(off)//終止有時,程序中會有些函數會使編譯器發出你熟知而想忽略的警告,如「Parameter xxx is never used in function xxx」,可以這樣: #pragmawarn—100//#100intinsert_record(REC*r){/*functionbody*/}#pragmawarn+100//#100backon函數會產生一條有唯一特徵碼100的警告信息,如此可暫時終止該警告。
每個編譯器對#pragma的實現不同,在一個編譯器中有效在別的編譯器中幾乎無效。可從編譯器的文檔中查看。 #pragmapack(n)和#pragmapop()structsample{chara;doubleb;};當sample結構沒有加#pragma pack(n)的時候,sample按最大的成員那個對齊;
(所謂的對齊是指對齊數為n時,對每個成員進行對齊,既如果成員a的大小小於n則將a擴大到n個大小;
如果a的大小大於n則使用a的大小;)所以上面那個結構的大小為16位元組.
當sample結構加#pragma pack(1)的時候,sizeof(sample)=9位元組;無空位元組。
(另註:當n大於sample結構的最大成員的大小時,n取最大成員的大小。
所以當n越大時,結構的速度越快,大小越大;反之則)
#pragma pop()就是取消#pragma pack(n)的意思了,也就是說接下來的結構不用#pragma pack(n) #pragmacomment(comment-type,[commentstring])comment-type是一個預定義的標識符,指定注釋的類型,應該是compiler,exestr,lib,linker之一。
comment string是一個提供為comment-type提供附加信息的字元串。
注釋類型:
1、compiler:
放置編譯器的版本或者名字到一個對象文件,該選項是被linker忽略的。
2、exestr:
在以後的版本將被取消。
3、lib:
放置一個庫搜索記錄到對象文件中,這個類型應該是和comment string(指定你要Linker搜索的lib的名稱和路徑)這個庫的名字放在Object文件的默認庫搜索記錄的後面,linker搜索這個這個庫就像你在命令行輸入這個命令一樣。你可以在一個源文件中設置多個庫記錄,它們在object文件中的順序和在源文件中的順序一樣。如果默認庫和附加庫的次序是需要區別的,使用Z編譯開關是防止默認庫放到object模塊。
4、linker:
指定一個連接選項,這樣就不用在命令行輸入或者在開發環境中設置了。
只有下面的linker選項能被傳給Linker. /DEFAULTLIB,/EXPORT,/INCLUDE,/MANIFESTDEPENDENCY,/MERGE,/SECTION(1) /DEFAULTLIB:library
/DEFAULTLIB 選項將一個 library 添加到 LINK 在解析引用時搜索的庫列表。用 /DEFAULTLIB指定的庫在命令行上指定的庫之後和 .obj 文件中指定的默認庫之前被搜索。忽略所有默認庫 (/NODEFAULTLIB) 選項重寫 /DEFAULTLIB:library。如果在兩者中指定了相同的 library 名稱,忽略庫 (/NODEFAULTLIB:library) 選項將重寫 /DEFAULTLIB:library。
(2)/EXPORT:entryname[,@ordinal[,NONAME]][,DATA]
使用該選項,可以從程序導出函數,以便其他程序可以調用該函數。也可以導出數據。通常在 DLL 中定義導出。entryname是調用程序要使用的函數或數據項的名稱。ordinal 在導出表中指定范圍在 1 至 65,535 的索引;如果沒有指定 ordinal,則 LINK 將分配一個。NONAME關鍵字只將函數導出為序號,沒有 entryname。
DATA 關鍵字指定導出項為數據項。客戶程序中的數據項必須用 extern __declspec(dllimport)來聲明。
有三種導出定義的方法,按照建議的使用順序依次為:
源代碼中的 __declspec(dllexport).def 文件中的 EXPORTS 語句LINK 命令中的 /EXPORT 規范所有這三種方法可以用在同一個程序中。LINK 在生成包含導出的程序時還創建導入庫,除非生成中使用了 .exp 文件。
LINK 使用標識符的修飾形式。編譯器在創建 .obj 文件時修飾標識符。如果 entryname以其未修飾的形式指定給鏈接器(與其在源代碼中一樣),則 LINK 將試圖匹配該名稱。如果無法找到唯一的匹配名稱,則 LINK 發出錯誤信息。當需要將標識符指定給鏈接器時,請使用 Dumpbin 工具獲取該標識符的修飾名形式。
(3)/INCLUDE:symbol
/INCLUDE 選項通知鏈接器將指定的符號添加到符號表。
若要指定多個符號,請在符號名稱之間鍵入逗號 (,)、分號 (;) 或空格。在命令行上,對每個符號指定一次 /INCLUDE:symbol。
鏈接器通過將包含符號定義的對象添加到程序來解析 symbol。該功能對於添包含不會鏈接到程序的庫對象非常有用。用該選項指定符號將通過 /OPT:REF 重寫該符號的移除。
我們經常用到的是#pragma comment(lib,*.lib)這類的。#pragma comment(lib,Ws2_32.lib)表示鏈接Ws2_32.lib這個庫。 和在工程設置里寫上鏈入Ws2_32.lib的效果一樣,不過這種方法寫的 程序別人在使用你的代碼的時候就不用再設置工程settings了 介紹
用#pragma data_seg建立一個新的數據段並定義共享數據,其具體格式為: #pragmadata_seg(shareddata)HWNDsharedwnd=NULL;//共享數據#pragmadata_seg()-----------------------------------------------------------------
1,#pragma data_seg()一般用於DLL中。也就是說,在DLL中定義一個共享的有名字的數據段。最關鍵的是:這個數據段中的全局變數可以被多個進程共享,否則多個進程之間無法共享DLL中的全局變數。
2,共享數據必須初始化,否則微軟編譯器會把沒有初始化的數據放到.BSS段中,從而導致多個進程之間的共享行為失敗。例如, #pragmadata_seg(MyData)intg_Value;//.#pragmadata_seg()//DLL提供兩個介面函數:intGetValue(){returng_Value;}voidSetValue(intn){g_Value=n;}然後啟動兩個進程A和B,A和B都調用了這個DLL,假如A調用了SetValue(5); B接著調用int m = GetValue(); 那麼m的值不一定是5,而是一個未定義的值。因為DLL中的全局數據對於每一個調用它的進程而言,是私有的,不能共享的。假如你對g_Value進行了初始化,那麼g_Value就一定會被放進MyData段中。換句話說,如果A調用了SetValue(5); B接著調用int m = GetValue(); 那麼m的值就一定是5,這就實現了跨進程之間的數據通信。 #pragma region是Visual C++中特有的預處理指令。它可以讓你折疊特定的代碼塊,從而使界面更加清潔,便於編輯其他代碼。折疊後的代碼塊不會影響編譯。你也可以隨時展開代碼塊以進行編輯等操作。
格式: #pragmaregionname#pragmaendregioncomment使用示例如下: #pragmaregionVariablesHWNDhWnd;constsize_tMax_Length=20;//othervariables#.如上邊所示,需要折疊的代碼必須包含在#pragma region和#pragma endregion之間。#pragma region和#pragma endregion之後可以添加一些用來注釋的文字。當你折疊代碼塊後,這些文字會顯示在折疊的位置。
折疊代碼塊的方法:如同Visual C++中折疊函數、類、命名空間,當代碼被包含在如上所述的指令之間後,#pragma region這一行的左邊會出現一個「-」號,單擊以折疊內容,同時「-」號會變成「+」號,再次單擊可以展開代碼塊。
此預編譯指令在Visual Studio 2005及以上版本可以使用。但是在Visual Studio 2005中,當#pragma region之後包含類似「1st」這類的文字,會導致「error C2059: syntax error : 'bad suffix on number'」的編譯錯誤。避免使用數字或者將數字與字母分離可以解決這個問題。

㈣ 如何找到windows載入dll時,搜索的路徑順序

dll查找的路徑順序如下:
a. 應用程序所在目錄;

b. 系統目錄。 GetSystemDirectory 返回的目錄,通常是系統盤\Windows\System32;

c. 16位系統目錄。該項只是為了向前兼容的處理,可以不考慮;

d. Windows目錄。 GetWindowsDirectory 返回的目錄,通常是系統盤 \Windows ;

e. 當前目錄。GetCurrentDirectory返回的目錄;

f. 環境變數PATH中所有目錄。

如果"安全DLL查找模式"被禁用,查找順序如下:

a. 應用程序所在目錄;

b. 當前目錄。GetCurrentDirectory返回的目錄;

c. 系統目錄。 GetSystemDirectory 返回的目錄,通常是系統盤\Windows\System32;

d. 16位系統目錄。該項只是為了向前兼容的處理,可以不考慮;

e. Windows目錄。 GetWindowsDirectory 返回的目錄,通常是系統盤 \Windows ;

f. 環境變數PATH中所有目錄。

㈤ 在一個C++程序文件中,若要包含另外一個頭文件或程序文件,則應該使用什麼標識符開始的預處理命令」

#include <header.h>
#include "header.h"
兩種區別主要在於搜索路徑不同,或者優先順序不同,前者從系統或編譯器提供的頭文件中搜索,後者優先源文件目錄或項目目錄。

㈥ C語言中,運算符的優先順序和結合方向與編譯工具有關嗎在不同編譯工具下是如何處理的呢

首先優先順序和結合性與編譯器本身無關,只和標准有關

其次,你這里的問題和優先順序以及結合性無關,這是求值順序問題,而C語言中沒有規定求值順序,故實際上是無解的

http://bbs.csdn.net/topics/370153775

㈦ 寫c語言時候頭文件後面用<>和用" "有什麼區別嗎

一般地說,用<>括起來的是標准c語言函數,是編譯系統默認路徑下可找到的定義文件。
如果你需要編寫自己用的頭文件或其他文件需要引用時,普通不會存放在c語言編譯環境的目錄中,這時需要在編譯選項中添加搜索路徑,並在程序中用""括起來文件名,這樣編譯程序除了在標准系統目錄中搜索外,還到你指定的路徑中搜索。
由此,你用<>能編譯通過的地方可以全都換成""也沒有問題。

㈧ 預處理指令#pragma db code是什麼意思

一、作用是設定編譯器的狀態或者是指示編譯器完成一些特定的動作。#pragma指令對每個編譯器給出了一個方法,在保持與C和 C++語言完全兼容的情況下,給出主機或操作系統專有的特徵。依據定義,編譯指示是機器或操作系統專有的,且對於每個編譯器都是不同的。

二、常用的pragma指令的詳細解釋。
1.#pragma once。保證所在文件只會被包含一次,它是基於磁碟文件的,而#ifndef則是基於宏的。
2.#pragma warning。允許有選擇性的修改編譯器的警告消息的行為。有如下用法:
#pragma warning(disable:4507 34; once:4385; error:164) 等價於:
#pragma warning(disable:4507 34) // 不顯示4507和34號警告信息
#pragma warning(once:4385) // 4385號警告信息僅報告一次
#pragma warning(error:164) // 把164號警告信息作為一個錯誤
#pragma warning(default:176) // 重置編譯器的176號警告行為到默認狀態
同時這個pragma warning也支持如下格式,其中n代表一個警告等級(1---4):
#pragma warning(push) // 保存所有警告信息的現有的警告狀態
#pragma warning(push,n) // 保存所有警告信息的現有的警告狀態,並設置全局報警級別為n
#pragma warning(pop) // 恢叢 鵲木 孀刺 趐ush和pop之間所做的一切改動將取消
例如:
#pragma warning(push)
#pragma warning(disable:4705)
#pragma warning(disable:4706)
#pragma warning(disable:4707)
#pragma warning(pop)
在這段代碼後,恢復所有的警告信息(包括4705,4706和4707)。
3.#pragma hdrstop。表示預編譯頭文件到此為止,後面的頭文件不進行預編譯。BCB可以預編譯頭文件以 加快鏈接的速度,但如果所有頭文件都進行預編譯又可能占太多磁碟空間,所以使用這個選項排除一些頭文 件。
4.#pragma message。在標准輸出設備中輸出指定文本信息而不結束程序運行。用法如下:
#pragma message("消息文本")。當編譯器遇到這條指令時就在編譯輸出窗口中將「消息文本」列印出來。
5.#pragma data_seg。一般用於DLL中,它能夠設置程序中的初始化變數在obj文件中所在的數據段。如果未指定參數,初始化變數將放置在默認數據段.data中,有如下用法:
#pragma data_seg("Shared") // 定義了數據段"Shared",其中有兩個變數a和b
int a = 0; // 存儲在數據段"Shared"中
int b; // 存儲在數據段".bss"中,因為沒有初始化
#pragma data_seg() // 表示數據段"Shared"結束,該行代碼為可選的
對變數進行專門的初始化是很重要的,否則編譯器將把它們放在普通的未初始化數據段中而不是放在shared中。如上述的變數b其實是放在了未初始化數據段.bss中。
#pragma data_seg("Shared")
int j = 0; // 存儲在數據段"Shared"中
#pragma data_seg(push, stack1, "Shared2") //定義數據段Shared2,並將該記錄賦予別名stack1,然後放入內部編譯器棧中
int l = 0; // 存儲在數據段"Shared2"中
#pragma data_seg(pop, stack1) // 從內部編譯器棧中彈出記錄,直到彈出stack1,如果沒有stack1,則不做任何操作
int m = 0; // 存儲在數據段"Shared"中,如果沒有上述pop段,則該變數將儲在數據段"Shared2"中
6.#pragma code_seg。它能夠設置程序中的函數在obj文件中所在的代碼段。如果未指定參數,函數將放置在默認代碼段.text中,有如下用法:
void func1() { // 默認存儲在代碼段.text中
}
#pragma code_seg(".my_data1")
void func2() { // 存儲在代碼段.my_data1中
}
#pragma code_seg(push, r1, ".my_data2")
void func3() { // 存儲在代碼段.my_data2中
}
#pragma code_seg(pop, r1)
void func4() { // 存儲在代碼段.my_data1中
}
7.#pragma pack。用來改變編譯器的位元組對齊方式。常規用法為:
#pragma pack(n) //將編譯器的位元組對齊方式設為n,n的取值一般為1、2、4、8、16,一般默認為8
#pragma pack(show) //以警告信息的方式將當前的位元組對齊方式輸出
#pragma pack(push) //將當前的位元組對齊方式放入到內部編譯器棧中
#pragma pack(push,4) //將位元組對齊方式4放入到內部編譯器棧中,並將當前的內存對齊方式設置為4
#pragma pack(pop) //將內部編譯器棧頂的記錄彈出,並將其作為當前的內存對齊方式
#pragma pack(pop,4) //將內部編譯器棧頂的記錄彈出,並將4作為當前的內存對齊方式
#pragma pack(pop,r1) //r1為自定義的標識符,將內部編譯器中的記錄彈出,直到彈出r1,並將r1的值作為當前的內存對齊方式;如果r1不存在,當不做任何操作
8.#pragma comment。將一個注釋記錄放置到對象文件或可執行文件中。
其格式為:#pragma comment( comment-type [,"commentstring"] )。其中,comment-type是一個預定義的標識符,指定注釋的類型,應該是compiler,exestr,lib,linker,user之一。
compiler:放置編譯器的版本或者名字到一個對象文件,該選項是被linker忽略的。
exestr:在以後的版本將被取消。
lib:放置一個庫搜索記錄到對象文件中,這個類型應該與commentstring(指定Linker要搜索的lib的名稱和路徑)所指定的庫類型一致。在對象文件中,庫的名字跟在默認搜索記錄後面;linker搜索這個這個庫就像你在命令行輸入這個命令一樣。你可以在一個源文件中設置多個庫搜索記錄,它們在obj文件中出現的順序與在源文件中出現的順序一樣。
如果默認庫和附加庫的次序是需要區別的,使用/Zl編譯開關可防止默認庫放到object模塊中。
linker:指定一個連接選項,這樣就不用在命令行輸入或者在開發環境中設置了。只有下面的linker選項能被傳給Linker:
/DEFAULTLIB
/EXPORT
/INCLUDE
/MANIFESTDEPENDENCY
/MERGE
/SECTION
(1)/DEFAULTLIB:library
/DEFAULTLIB選項將一個library添加到LINK在解析引用時搜索的庫列表。用/DEFAULTLIB指定的庫在命令行上指定的庫之後和obj文件中指定的默認庫之前被搜索。
忽略所有默認庫(/NODEFAULTLIB)選項重寫/DEFAULTLIB:library。如果在兩者中指定了相同的library名稱,忽略庫(/NODEFAULTLIB:library)選項將重寫/DEFAULTLIB:library。
(2)/EXPORT:entryname[,@ordinal[,NONAME]][,DATA]
使用該選項,可以從程序導出函數以便其他程序可以調用該函數,也可以導出數據。通常在DLL中定義導出。
entryname是調用程序要使用的函數或數據項的名稱。ordinal為導出表的索引,取值范圍在1至65535;如果沒有指定ordinal,則LINK將分配一個。NONAME關鍵字只將函數導出為序號,沒有entryname。DATA 關鍵字指定導出項為數據項。客戶程序中的數據項必須用extern __declspec(dllimport)來聲明。
有三種導出定義的方法,按照建議的使用順序依次為:
源代碼中的__declspec(dllexport)
.def文件中的EXPORTS語句
LINK命令中的/EXPORT規范
所有這三種方法可以用在同一個程序中。LINK在生成包含導出的程序時還要創建導入庫,除非在生成過程中使用了.exp 文件。
LINK使用標識符的修飾形式。編譯器在創建obj文件時修飾標識符。如果entryname以其未修飾的形式指定給鏈接器(與其在源代碼中一樣),則LINK將試圖匹配該名稱。如果無法找到唯一的匹配名稱,則LINK發出錯誤信息。當需要將標識符指定給鏈接器時,請使用Dumpbin工具獲取該標識符的修飾名形式。
(3)/INCLUDE:symbol
/INCLUDE選項通知鏈接器將指定的符號添加到符號表。若要指定多個符號,請在符號名稱之間鍵入逗號(,)、分號(;)或空格。在命令行上,對每個符號需指定一次/INCLUDE:symbol。
鏈接器通過將包含符號定義的對象添加到程序來解析symbol。該功能對於添加不會鏈接到程序的庫對象非常有用。
用該選項所指定的符號將覆蓋通過/OPT:REF對該符號進行的移除操作。
(4)/MANIFESTDEPENDENCY:manifest_dependency
/MANIFESTDEPENDENCY允許你指定位於manifest文件的段的屬性。/MANIFESTDEPENDENCY信息可以通過下面兩種方式傳遞給LINK:
直接在命令行運行/MANIFESTDEPENDENCY
通過#pragma comment
(5)/MERGE:from=to
/MERGE選項將第一個段(from)與第二個段(to)進行聯合,並將聯合後的段命名為to的名稱。
如果第二個段不存在,LINK將段(from)重命名為to的名稱。
/MERGE選項對於創建VxDs和重寫編譯器生成的段名非常有用。
(6)/SECTION:name,[[!]{DEKPRSW}][,ALIGN=#]
/SECTION選項用來改變段的屬性,當指定段所在的obj文件編譯的時候重寫段的屬性集。
可移植的可執行文件(PE)中的段(section)與新可執行文件(NE)中的節區(segment)或資源大致相同。
段(section)中包含代碼或數據。與節區(segment)不同的是,段(section)是沒有大小限制的連續內存塊。有些段中的代碼或數據是你的程序直接定義和使用的,而有些數據段是鏈接器和庫管理器(lib.exe)創建的,並且包含了對操作系統來說很重要的信息。
/SECTION選項中的name是大小寫敏感的。
不要使用以下名稱,因為它們與標准名稱會沖突,例如,.sdata是RISC平台使用的。
.arch
.bss
.data
.edata
.idata
.pdata
.rdata
.reloc
.rsrc
.sbss
.sdata
.srdata
.text
.xdata
為段指定一個或多個屬性。屬性不是大小寫敏感的。對於一個段,你必須將希望它具有的屬性都進行指定;如果某個屬性未指定,則認為是不具備這個屬性。如果你未指定R,W或E,則已存在的讀,寫或可執行狀態將不發生改變。
要對某個屬性取否定意義,只需要在屬性前加感嘆號(!)。
E:可執行的
R:可讀取的
W:可寫的
S:對於載入該段的鏡像的所有進程是共享的
D:可廢棄的
K:不可緩存的
P:不可分頁的
注意K和P是表示否定含義的。
PE文件中的段如果沒有E,R或W屬性集,則該段是無效的。
ALIGN=#選項讓你為一個具體的段指定對齊值。
user:放置一個常規注釋到一個對象文件中,該選項是被linker忽略的。
9.#pragma section。創建一個段。
其格式為:#pragma section( "section-name" [, attributes] )
section-name是必選項,用於指定段的名字。該名字不能與標准段的名字想沖突。可用/SECTION查看標准段的名稱列表。
attributes是可選項,用於指定段的屬性。可用屬性如下,多個屬性間用逗號(,)隔開:
read:可讀取的
write:可寫的
execute:可執行的
shared:對於載入該段的鏡像的所有進程是共享的
nopage:不可分頁的,主要用於Win32的設備驅動程序中
nocache:不可緩存的,主要用於Win32的設備驅動程序中
discard:可廢棄的,主要用於Win32的設備驅動程序中
remove:非內存常駐的,僅用於虛擬設備驅動(VxD)中
如果未指定屬性,默認屬性為read和write。
在創建了段之後,還要使用__declspec(allocate)將代碼或數據放入段中。
例如:
//pragma_section.cpp
#pragma section("mysec",read,write)
int j = 0;
__declspec(allocate("mysec"))
int i = 0;
int main(){}
該例中, 創建了段"mysec",設置了read,write屬性。但是j沒有放入到該段中,而是放入了默認的數據段中,因為它沒有使用__declspec(allocate)進行聲明;而i放入了該段中,因為使用__declspec(allocate)進行了聲明。
10.#pragma push_macro與#pragma pop_macro。前者將指定的宏壓入棧中,相當於暫時存儲,以備以後使用;後者將棧頂的宏出棧,彈出的宏將覆蓋當前名稱相同的宏。例如:
#include
#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

㈨ 如何使用CMake進行交叉編譯

cmake交叉編譯配置

很多時候,我們在開發的時候是面對嵌入式平台,因此由於資源的限制需要用到相關的交叉編譯。即在你host宿主機上要生成target目標機的程序。裡面牽扯到相關頭文件的切換和編譯器的選擇以及環境變數的改變等,我今天僅僅簡單介紹下相關CMake在面對交叉編譯的時候,需要做的一些准備工作。

CMake給交叉編譯預留了一個很好的變數CMAKE_TOOLCHAIN_FILE,它定義了一個文件的路徑,這個文件即toolChain,裡面set了一系列你需要改變的變數和屬性,包括C_COMPILER,CXX_COMPILER,如果用Qt的話需要更改QT_QMAKE_EXECUTABLE以及如果用BOOST的話需要更改的BOOST_ROOT(具體查看相關Findxxx.cmake裡面指定的路徑)。CMake為了不讓用戶每次交叉編譯都要重新輸入這些命令,因此它帶來toolChain機制,簡而言之就是一個cmake腳本,內嵌了你需要改變以及需要set的所有交叉環境的設置。

toolChain腳本中設置的幾個重要變數

1.CMAKE_SYSTEM_NAME:

即你目標機target所在的操作系統名稱,比如ARM或者Linux你就需要寫"Linux",如果Windows平台你就寫"Windows",如果你的嵌入式平台沒有相關OS你即需要寫成"Generic",只有當CMAKE_SYSTEM_NAME這個變數被設置了,CMake才認為此時正在交叉編譯,它會額外設置一個變數CMAKE_CROSSCOMPILING為TRUE.

2. CMAKE_C_COMPILER:

顧名思義,即C語言編譯器,這里可以將變數設置成完整路徑或者文件名,設置成完整路徑有一個好處就是CMake會去這個路徑下去尋找編譯相關的其他工具比如linker,binutils等,如果你寫的文件名帶有arm-elf等等前綴,CMake會識別到並且去尋找相關的交叉編譯器。

3. CMAKE_CXX_COMPILER:

同上,此時代表的是C++編譯器。

4. CMAKE_FIND_ROOT_PATH:

指定了一個或者多個優先於其他搜索路徑的搜索路徑。比如你設置了/opt/arm/,所有的Find_xxx.cmake都會優先根據這個路徑下的/usr/lib,/lib等進行查找,然後才會去你自己的/usr/lib和/lib進行查找,如果你有一些庫是不被包含在/opt/arm裡面的,你也可以顯示指定多個值給CMAKE_FIND_ROOT_PATH,比如

set(CMAKE_FIND_ROOT_PATH /opt/arm /opt/inst)

該變數能夠有效地重新定位在給定位置下進行搜索的根路徑。該變數默認為空。當使用交叉編譯時,該變數十分有用:用該變數指向目標環境的根目錄,然後CMake將會在那裡查找。

5. CMAKE_FIND_ROOT_PATH_MODE_PROGRAM:

對FIND_PROGRAM()起作用,有三種取值,NEVER,ONLY,BOTH,第一個表示不在你CMAKE_FIND_ROOT_PATH下進行查找,第二個表示只在這個路徑下查找,第三個表示先查找這個路徑,再查找全局路徑,對於這個變數來說,一般都是調用宿主機的程序,所以一般都設置成NEVER

6. CMAKE_FIND_ROOT_PATH_MODE_LIBRARY:

對FIND_LIBRARY()起作用,表示在鏈接的時候的庫的相關選項,因此這里需要設置成ONLY來保證我們的庫是在交叉環境中找的.

7. CMAKE_FIND_ROOT_PATH_MODE_INCLUDE:

對FIND_PATH()和FIND_FILE()起作用,一般來說也是ONLY,如果你想改變,一般也是在相關的FIND命令中增加option來改變局部設置,有NO_CMAKE_FIND_ROOT_PATH,ONLY_CMAKE_FIND_ROOT_PATH,BOTH_CMAKE_FIND_ROOT_PATH

8. BOOST_ROOT:

對於需要boost庫的用戶來說,相關的boost庫路徑配置也需要設置,因此這里的路徑即ARM下的boost路徑,裡面有include和lib。

9. QT_QMAKE_EXECUTABLE:

對於Qt用戶來說,需要更改相關的qmake命令切換成嵌入式版本,因此這里需要指定成相應的qmake路徑(指定到qmake本身)

toolChain demo

# this is required
SET(CMAKE_SYSTEM_NAME Linux)

# specify the cross compiler
SET(CMAKE_C_COMPILER /opt/arm/usr/bin/ppc_74xx-gcc)
SET(CMAKE_CXX_COMPILER /opt/arm/usr/bin/ppc_74xx-g++)

# where is the target environment
SET(CMAKE_FIND_ROOT_PATH /opt/arm/ppc_74xx /home/rickk/arm_inst)

# search for programs in the build host directories (not necessary)
SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
# for libraries and headers in the target directories
SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)

# configure Boost and Qt
SET(QT_QMAKE_EXECUTABLE /opt/qt-embedded/qmake)
SET(BOOST_ROOT /opt/boost_arm)

這樣就完成了相關toolChain的編寫,之後,你可以靈活的選擇到底採用宿主機版本還是開發機版本,之間的區別僅僅是一條-DCMAKE_TOOLCHAIN_FILE=./toolChain.cmake,更爽的是,如果你有很多程序需要做轉移,但目標平台是同一個,你僅僅需要寫一份toolChain放在一個地方,就可以給所有工程使用。

㈩ 如何更改動態鏈接庫的路徑優先順序

你的運行目錄和dll庫不在一個目錄肯定會找不到的。
QCoreApplication::addLibraryPath("./lib");把這句話加到main.cpp裡面。

閱讀全文

與編譯搜索路徑優先順序相關的資料

熱點內容
怎樣在打開微信前加密 瀏覽:664
旺旺聊天記錄怎麼加密 瀏覽:411
王安憶長恨歌pdf 瀏覽:619
mobile文件夾可以卸載嗎 瀏覽:280
什麼是2通道伺服器 瀏覽:346
mc正版怎麼開伺服器地址 瀏覽:408
樂高解壓朋友圈 瀏覽:14
linux軟raid性能 瀏覽:368
貼片機編程軟體下載 瀏覽:360
mooc大學樂學python答案 瀏覽:408
怎麼投訴途虎app 瀏覽:37
安卓重力感應怎麼關 瀏覽:720
我的世界ios怎麼建伺服器地址 瀏覽:759
伺服器埠ip都是什麼意思 瀏覽:263
華為主題軟體app怎麼下 瀏覽:840
我們的圖片能夠收藏加密嗎 瀏覽:979
mysql空值命令 瀏覽:213
python整點秒殺 瀏覽:885
怎麼樣互傳app 瀏覽:293
python分布式抓包 瀏覽:38