編譯為本機的函數
A. C編譯器編譯過的函數怎樣在C++中使用
本人以前的學習筆記(在網上找的):看了後,你一定可以解決
15.在C++ 程序中調用被C 編譯器編譯後的函數,為什麼要加extern 「C」?
首先,作為extern是C/C++語言中表明函數和全局變數作用范圍(可見性)的關鍵字,該關鍵字告訴編譯器,其聲明的函數和變數可以在本模塊或其它模塊中使用。
通常,在模塊的頭文件中對本模塊提供給其它模塊引用的函數和全局變數以關鍵字extern聲明。例如,如果模塊B欲引用該模塊A中定義的全局變數和函數時只需包含模塊A的頭文件即可。這樣,模塊B中調用模塊A中的函數時,在編譯階段,模塊B雖然找不到該函數,但是並不會報錯;它會在連接階段中從模塊A編譯生成的目標代碼中找到此函數
extern "C"是連接申明(linkage declaration),被extern "C"修飾的變數和函數是按照c語言方式編譯和連接的,來看看C++中對類似C的函數是怎樣編譯的:
作為一種面向對象的語言,C++支持函數重載,而過程式語言C則不支持。函數被C++編譯後在符號庫中的名字與C語言的不同。例如,假設某個函數的原型為:
void foo( int x, int y );
該函數被C編譯器編譯後在符號庫中的名字為_foo,而C++編譯器則會產生像_foo_int_int之類的名字(不同的編譯器可能生成的名字不同,但是都採用了相同的機制,生成的新名字稱為「mangled name」)。
_foo_int_int這樣的名字包含了函數名、函數參數數量及類型信息,C++就是靠這種機制來實現函數重載的。例如,在C++中,函數void foo( int x, int y )與void foo( int x, float y )編譯生成的符號是不相同的,後者為_foo_int_float。
同樣地,C++中的變數除支持局部變數外,還支持類成員變數和全局變數。用戶所編寫程序的類成員變數可能與全局變數同名,我們以"."來區分。而本質上,編譯器在進行編譯時,與函數的處理相似,也為類中的變數取了一個獨一無二的名字,這個名字與用戶程序中同名的全局變數名字不同。
未加extern "C"聲明時的連接方式
假設在C++中,模塊A的頭文件如下:
// 模塊A頭文件 moleA.h
#ifndef MODULE_A_H
#define MODULE_A_H
int foo( int x, int y );
#endif
在模塊B中引用該函數:
// 模塊B實現文件 moleB.cpp
#i nclude "moleA.h"
foo(2,3);
實際上,在連接階段,連接器會從模塊A生成的目標文件moleA.obj中尋找_foo_int_int這樣的符號!
加extern "C"聲明後的編譯和連接方式
加extern "C"聲明後,模塊A的頭文件變為:
// 模塊A頭文件 moleA.h
#ifndef MODULE_A_H
#define MODULE_A_H
extern "C" int foo( int x, int y );
#endif
在模塊B的實現文件中仍然調用foo( 2,3 ),其結果是:
(1)模塊A編譯生成foo的目標代碼時,沒有對其名字進行特殊處理,採用了C語言的方式;
(2)連接器在為模塊B的目標代碼尋找foo(2,3)調用時,尋找的是未經修改的符號名_foo。
如果在模塊A中函數聲明了foo為extern "C"類型,而模塊B中包含的是extern int foo( int x, int y ) ,則模塊B找不到模塊A中的函數;反之亦然。
所以,可以用一句話概括extern 「C」這個聲明的真實目的(任何語言中的任何語法特性的誕生都不是隨意而為的,來源於真實世界的需求驅動。我們在思考問題時,不能只停留在這個語言是怎麼做的,還要問一問它為什麼要這么做,動機是什麼,這樣我們可以更深入地理解許多問題):實現C++與C及其它語言的混合編程。
明白了C++中extern "C"的設立動機,我們下面來具體分析extern "C"通常的使用技巧:
extern "C"的慣用法
(1)在C++中引用C語言中的函數和變數,在包含C語言頭文件(假設為cExample.h)時,需進行下列處理:
extern "C"
{
#i nclude "cExample.h"
}
而在C語言的頭文件中,對其外部函數只能指定為extern類型,C語言中不支持extern "C"聲明,在.c文件中包含了extern "C"時會出現編譯語法錯誤。
C++引用C函數例子工程中包含的三個文件的源代碼如下:
/* c語言頭文件:cExample.h */
#ifndef C_EXAMPLE_H
#define C_EXAMPLE_H
extern int add(int x,int y);
#endif
/* c語言實現文件:cExample.c */
#i nclude "cExample.h"
int add( int x, int y )
{
return x + y;
}
// c++實現文件,調用add:cppFile.cpp
extern "C"
{
#i nclude "cExample.h"
}
int main(int argc, char* argv[])
{
add(2,3);
return 0;
}
如果C++調用一個C語言編寫的.DLL時,當包括.DLL的頭文件或聲明介面函數時,應加extern "C" { }。
(2)在C中引用C++語言中的函數和變數時,C++的頭文件需添加extern "C",但是在C語言中不能直接引用聲明了extern "C"的該頭文件,應該僅將C文件中將C++中定義的extern "C"函數聲明為extern類型。
C引用C++函數例子工程中包含的三個文件的源代碼如下:
//C++頭文件 cppExample.h
#ifndef CPP_EXAMPLE_H
#define CPP_EXAMPLE_H
extern "C" int add( int x, int y );
#endif
//C++實現文件 cppExample.cpp
#i nclude "cppExample.h"
int add( int x, int y )
{
return x + y;
}
/* C實現文件 cFile.c
/* 這樣會編譯出錯:#i nclude "cExample.h" */
extern int add( int x, int y );
int main( int argc, char* argv[] )
{
add( 2, 3 );
return 0;
}
15題目的解答請參考《C++中extern 「C」含義深層探索》註解:
B. vb編譯為「本機代碼」和「P-代碼」有什麼不同
按照預設規定,Visual Basic 將應用程序編譯成可運行的解釋型或 P-code 程序。運行時,動態鏈接庫 (DLL) 將翻譯或解釋執行程序中的指令。
用「本機代碼」選項來編譯工程意味著您寫的代碼將完整地編譯為處理器晶元的本地指令,而不是編譯為p-code。這將大大加速循環和數學計算,並可以加速對 MSVBVM60.DLL提供的服務程序的調用。然而,這並不能減少對 DLL 的需要。
選中「編譯為P-代碼」,VB將應用程序編譯成解釋執行的P-代碼程序。運行P-代碼程序時,動態鏈接庫(DLL)將翻譯或解釋執行程序中的指令。在許多情況下,運行本機代碼比運行解釋型代碼本質上要快得多。
P代碼似乎沒什麼優點喔,我唯一知道的就是編譯為P代碼較難破解。
Microsoft Visual Basic 6.0是一個RAD(Rapid Application Development)工具,它具有把應用程序編譯成P代碼或本機代碼的靈活性。把應用程序編譯成P代碼可以使代碼的長度被優化為最小。這種代碼長度較 小的特點使P代碼在低帶寬情況下成為創建Internet應用程序的最佳選擇。本機代碼的編譯過程對速度進行了很好的優化(將快至20倍),但是所產生的 可執行文件長度變大。Visual Basic 6.0是既支持通過P代碼又支持通過本機代碼快速開發應用程序的唯一RAD工具。
p代碼運行可能要慢一些,但是兼容性較好、文件小,發布時建議使用P代碼
這條意見 好像不對哦。
兩種都應該要vb運行庫的,一個要的是速度,一個要的是文件大小。
按照默認規定,Visual Basic將應用程序編譯成可運行的解釋型或P代碼(P-Code)程序。運行時,動態鏈接庫(DLL)將翻譯或解釋執行程序中的指令。在許多情況下,運行本機代碼比運行解釋型代碼本質上要快的多。
編譯為本機代碼時應注意以下一些事項:
1、若代碼做了大量固定類型的、非字元串變數的基本操作,則其產生的本機代碼將比編譯的P-Code操作碼產生最大的反差。但是,對於復雜的經濟計算或生成分形圖形,用本機代碼有很多好處。
2、計算密集型程序或在局部數據結構中處理大量的位和位元組操作的程序,用本機代碼就可獲得明顯的好處。
3、在多數的程序中,特別是那些含有大量Windows Api調用、COM方法調用和字元串操作的程序中,本機代碼不比P-Code快多少。
4、含有大量子常式調用而非內嵌過程的代碼,用本機代碼也不是很快。
C. 為什麼編譯器將閉包和本地函數以不同的方式
函數閉包 種問題本身雖中國絡見種提其實 Javascript 實現機制清楚胡亂猜測導致誤解 首先函數管匿名函數閉包間根本沒任何關系 所謂閉包究竟中國絡說雲霧講高深莫測其實要稍微些編譯器實現機制認識知道閉包其實非簡單東西 我先看看面代碼: function funcA() { var a = 依, b = 貳; return funcB(); function funcB() { // 注意a b 本函數根本沒定義竟能訪問 return a + b; } } var a = funcA(); // a 等於 三 面代碼神奇幾點: 依、函數嵌套定義( C/C++ 行) 貳、嵌套函數訪問級函數局部變數 先說嵌套其實能力沒神奇C/C++ 編譯器稍作修改能支持實現雖函數嵌套實用價值比較訪問級函數局部變數啊且我知道 Javascript 嵌套函數層層嵌套訪問內層函數能夠訪問頂層函數變數非用 說閉包關系呢 閉包用實現種嵌套能夠層層向訪問變數功能簡單編譯器技巧用使內部函數能夠訪問級函數變數 簡單說具體實現每函數附加額外隱藏象象其實叫做閉包象別管名字叫普通象沒神奇記錄本函數內部變數列表已且閉包象保存指向級函數閉包象引用 形鏈條我函數訪問變數候編譯器先看看本閉包底沒變數沒向尋找找用直找沒提示錯 明白事點按照面式構造閉包像固定其實每調用函數候都單獨創建新閉包象調用應起其實閉包鏈態創建 其實要說清楚問題配幾圖間所限我細說能理解疑問慢慢接觸知道 解釋段代碼加深理解 function X() { return function() { // ... } } 注意X面返匿名函數定要記住函數由於嵌套定義 X 閉包象鏈接 X 閉包象所匿名函數訪問 X 內部變數其實簡單管嵌套少層匿名名我看定義嵌套關系知道閉包鏈整鏈條其順理章 推薦兩讓走內普遍存誤區看 ECMA-貳陸貳, 5e麵包含所標准化 Javascript 算實現細節另外研究 Google v吧 引擎自代碼編譯調試問題能搞清楚
D. 請問C中編譯函數的順序
不知道你怎麼想的?
include的內容只有在程序中用到時才會被編譯;
在使用main()的C程序中,沒有判斷和轉折語句外,其它函數都是順序執行。
現在都用C++,面向對象了。順序指令只用於單任務系統。
E. c語言中的函數可不可以單獨進行編譯
是可以的。
庫函數是把函數放到庫里,供別人使用的一種方式。函數庫是由系統建立的具有一定功能的函數的集合。庫中存放函數的名稱和對應的目標代碼,以及連接過程中所需的重定位信息。用戶也可以根據自己的需要建立自己的用戶函數庫。
使用C語言的語句直接計算sin或cos函數,就需要編寫頗為復雜的程序。因為C語言的語句中沒有提供直接計算sin或cos函數的語句。又如為了顯示一段文字,我們在C語言中也找不到顯示語句,只能使用庫函數printf。
(5)編譯為本機的函數擴展閱讀
函數庫的分類
1、字元串、內存和字元函數
需要的包含文件:string.h、mem.h、ctype.h或string.h;
2、數學函數
需要的包含文件:math.h;
3、動態存儲分配
需要的包含文件:alloc.h或stdlib.h ;
F. excel如何編譯現成函數
比如,輸入=IF(A1>10,A1,"")表示:如果A1>10,就顯示A1;否則留空。
G. vb應用程序除了以解釋方式進行,還可以以什麼方式進行
vb應用程序除了以解釋方式進行,還可以編譯成本機代碼,在計算機的系統下直接運行。
將工程編譯成本機代碼
如果擁有VisualBasic的專業版或企業版,既可以將代碼編譯成標準的VisualBasic 偽代碼格式,也可以編譯成本機代碼格式。本機代碼編譯提供了偽代碼編譯所沒有的關於優化和調試的幾個選項。
P-code或偽代碼,是介於Basic 程序中的高級指令和計算機處理器執行的低級本機代碼之間的一種中間步驟。在運行時刻,VisualBasic 將每一句偽代碼轉換成本機代碼。如果將程序直接編譯成本機代碼,則取消了偽代碼這一中間步驟。
可以使用象在VisualC++中提供的調試環境之類的標準的本機代碼調試工具來調試編譯後的本機代碼。也可以使用例如在VisualC++ 的語言中提供的優化和調試本機代碼的選項。例如,可以根據代碼運行速度和大小優化代碼。
注意所有用VisualBasic創建的工程都使用運行時DLL (MSVBVM60.DLL)服務。在DLL所提供的服務當中有您應用程序的啟動和關閉代碼、窗體和內部控制項的功能,以及 Format和CLng
的運行時函數。
用「本機代碼」選項來編譯工程意味著您寫的代碼將完整地編譯為處理器晶元的本地指令,而不是編譯為p-code。這將大大加速循環和數學計算,並可以加速對 MSVBVM60.DLL提供的服務程序的調用。然而,這並不能減少對DLL的需要。
要將工程編譯成本機代碼,請按照以下步驟執行:
1.在「工程」窗口,選擇希望編譯的工程。
2.從「工程」菜單選擇「工程屬性」。
3.在「工程屬性」對話框,單擊「編譯」選項卡。
H. VB6自帶編譯器的「本機代碼」和「P代碼」各是什麼求答案
該選項卡設置工程編譯時的條件。選項卡選項「編譯為 P-代碼」
用 p 代碼來編譯工程。存儲在 .vbp 文件中的設置值將被覆蓋掉。
「編譯為本機代碼」
用帶有選定最優化的原碼來編譯工程。存儲在 .vbp 文件中的設置值將被覆蓋掉。
「快速代碼優化」- 通過指示編譯器在速度和大小之間首選速度,使 .exe 和 .dll 文件的速度最快。編譯器可以減少許多功能上跟機器碼序列相同的構造。在某些情況下,這種不同提供了用大小來換取速度的權衡交換。
「小代碼優化」- 通過指示編譯器在速度和大小之間首選大小,來使 .exe 和 .dll 文件最小。編譯器可以減少許多功能上跟機器碼序列相同的構造。如果不選中這個選項,代碼可能就會大一些,但是速度會更快一些。
「非優化」- 無優化地編譯。
「流行的 Pentium Pro™」- 優化所創建的代碼,優化方向是使之更有利於 Pentium Pro™ 處理器來處理。如果在程序中使用了這個選項,則意味著僅僅是為 Pentium Pro™ 處理器所創建的代碼。用此選項產生的代碼仍然可以在更早期的處理器上運行,但是工作起來性能不是那麼好。
「創建符號化調試信息」- 在可執行文件或者 DLL 文件中產生符號調試信息。用此選項創建的可執行文件可以用 Visual C++ 或者具有 CodeView 風格調試信息的調試器來調試。設置這個選項將為可執行文件產生一個帶有符號信息的 .pdb 文件。
「高級優化」
顯示「高級優化」對話框。
給程序設置一個基地址,從而覆蓋 .dll 文件的預設位置(在 0 X 10,000,000 處)。操作系統首先試圖在指定的或者預設的位置載入一個程序。如果沒有足夠空間,那麼系統將重新定位該程序。
I. 編譯程序時它說本地函數定義不合法,而這函數我是在其他函數中調用的,是什麼原因呢
(1) BOOL CVEmailDlg::CapSend() -- BOOL用大寫
(2) VEmailDlg.h 頭文件中加入原型聲明
BOOL CapSend();
J. 用C語言編寫軟體時 老是出現本地函數定義錯誤怎麼辦
換一個編譯工具,我前幾天也是,用codeblock編譯經常出現這種問題,說主函數返回為int型,換了Visual C++ 6.0就不會出現這個問題,希望對你有用!