C編譯系統自動調用
1. TKstudi C編譯器怎麼設置
VC就很了不起,因為使用這樣傻瓜化的工具只能讓你看不到事物的本質。接下來我們就來深入的認識Turbo C編譯器。 廣義的編譯器,包括了代碼編譯器(compiler),目標文件鏈接器(linker),庫文件管理工具(如tc的tlib,gcc的ar),編譯驅動工具(如VC的NMake,gcc的make),ANSI c/c++標準的頭文件和庫文件,擴展的頭文件和庫文件,集成開發環境(IDE),等等與編譯相關的工具,所有這些工具的集合,就組成了廣義上的編譯器。
狹義的編譯器,則僅指compiler。compiler只負責將源代碼,即.c/.cxx/.cpp文件編譯成為目標文件.o/.obj。編譯過程的輸入是源文件,包括自己書寫的.c和.h以及系統提供的.h文件,編譯的輸出是目標文件。需要強調的一點時,在compile階段,只處理源文件,所以不需要庫文件和額外的目標文件的參與,因此,只要代碼在語法上沒有錯誤,compile就一定能產生目標文件。
對於一個廣義的編譯器來說以下幾個部分是必備的:1.compiler,2.linker,3.系統提供的頭文件和庫文件。前面已經介紹了compiler,接下來看linker。
linker的功能是將目標文件進行裝配,將浮動的地址變為確定的地址,這個工作是通過修改目標文件的重定位項來實現的,其具體的過程可以參考"Linker & loader"這本書,這是一本詳細介紹linker和loader的好書,在此做個推薦。總之,link這一階段處理的輸入是目標文件,其輸出是可執行文件,或動態庫。
任何一個編譯器都會提供庫文件和與之對應的頭文件,C/C++編譯器一般都提供ANSI C/C++的庫和相應的頭文件。
從現在起我們就需要建立起一個概念,就是廣義的編譯過程,實際上是由編譯和鏈接兩個基本步驟組成的,如果能深刻的理解這兩個步驟,就是一大進步了。
在編譯器里,有一些默認的規定,我們需要了解。在編譯器中,bin目錄用於存放compiler、linker等工具,include目錄用於存放頭文件,lib目錄用存放庫文件,大多數的編譯器的目錄就是按這個來組織的。
接下來看Turbo C為我們提供了些什麼
bin目錄中:
CPP.EXE 是一個c語言預處理工具,就是負責對源代碼進行預編譯處理,不要理解為c++編譯器
TCC.EXE 是一個C語言的編譯器,可以將代碼編譯為目標文件,並且能自動調用tlink鏈接生成可執行文件
TASM.exe 是一個匯編工具,可以將x86的匯編代碼編譯成為目標文件
TLink.exe 是一個鏈接器,負責對目標文件、庫文件等進行鏈接
TLib.exe 是一個庫文件管理工具,可以將多個目標文件打包到一個庫文件里
BGIOBJ.exe 可以將BGI文件轉換為.obj文件
make.exe 符合GNU標準的make工具,可用於代碼編譯的管理
TURBOC.CFG tcc默認的編譯參數配置文件
以上所有的工具的使用方法都可以直接鍵入相應的命令進行查看,如鍵入tcc即可看到tcc的使用方法,因此這里不再講解。
BGI目錄中:
EGAVGA.BGI 是EGAVGA的bgi驅動
FONT目錄中:存放了BGI所使用到的各種字體文件
INCLUDE目錄中:是Turbo C的庫函數的所有的頭文件,當要使用某個庫函數時可以在這個目錄下搜索,找到其所在文件和原型,這里不在詳細敘述。
重點講一下Lib目錄:
init.obj文件是C語言的啟動代碼,它負責建立C程序運行的堆棧、初始化內存、調用C入口函數等。這部分代碼是使用匯編書寫的,其源代碼可以在TC(官方版)里找到,名稱為Init.ASM。
c0t.obj、c0s.obj、c0m.obj、c0c.obj、c0l.obj和c0h.obj文件,都是c code的入口函數實現,入口函數將會讀取環境變數,並調用c語言中的main函數,將命令行參數傳入main函數中,之後的控制權就交給了main函數,也就是我們常說的C的主函數main。由於Turbo C中有不同的內存模式,因此以上6個文件分別對應TC中6種不同的內存模式。
cc.lib、ch.lib、cl.lib、cm.lib、cs.lib五個文件都是TC提供的ANSI C標准庫的庫文件,分別對用不同的內存模式:
cc compact模式
ch huge模式
cl large模式
cm medium模式
cs small模式
2. 構造方法何時被調用
問題一:java中構造方法何時被調用 新建一個對象時被調用。也就是new的時候;
如:
public class A{
int i;
String c;
public A(){ } 無參構造方法
public A(int i,String c)
{
this.i = i;
this.c = c;
}兩參構造方法
public static void main(String[] args){
A a = new A() ;調用了無參構造方法;
A a1 = new A(5,vieri);調用了兩參構造方法
}
}
問題二:java 構造函數什麼時候被調用執行 在java語言 中,構造函數又稱構造方法。特殊性在於,與普通方法的區別是,他與類名相同,不返回結果也不加void返回值。構造函數的作用是初始化對象,即在創建對象時被系統調用(與普通方法不同,程序不能顯示調用構造函數)。構造函數還能夠被重載,即可以傳入參數,當程序中包含有帶參的構造函數時,系統將不會再提供的無參構造函數。構造函數特點:沒有函數返回值,構造函數名與類名相同;當創建類對象的時候調用其對應的構造方法去創建。每創建一個類的實例都去初始化它的所有變數是乏味的。如果一個對象在被創建時就完成了所有的初始工作,將是簡單的和簡潔的。因此,Java在類里提供了一個特殊的成員函數,叫做構造函數(Constructor)。 一個構造函數是對象被創建時初始對象的成員函數。它具有和它所在的類完全一樣的名字。一旦定義好一個構造函數,創建對象時就會自動調用它。構造函數沒有返回類型,即使是void類型也沒有。這是因為一個類的構造函數的返回值的類型就是這個類本身。構造函數的任務是初始化一個對象的內部狀態,所以用new操作符創建一個實例後,立刻就會得到一個清楚、可用的對象。 構造方法是一種特殊的方法,具有以下特點。 (1)構造方法的方法名必須與類名相同。 (2)構造方法沒有返回類型,也不能定義為void,在方法名前面不聲明方法類型。(3)構造方法的主要作用是完成對象的初始化工作,它能夠把定義對象時的參數傳給對象的域。 (4)構造方法不能由編程人員調用,而要系統調用。 (5)一個類可以定義多個構造方法,如果在定義類時沒有定義構造方法,則編譯系統會自動插入一個無參數的默認構造器,這個構造器不執行任何代碼。 (6)構造方法可以重載,以參數的個數,類型,或排列順序區分。
問題三:一個類的構造函數和析構函數什麼時候被調用 在對象被創建的時候就會調用構造函數,比如 聲明一個類class A{...},當你在main函數中
A a ; 定義一個對象a的時候, 就調用構造函數,默認構造函數都是無參數的 ,構造函數就相當給對象a初始化而已,就相當於c語言中 int a = 3 初始化a的值而已,因為你在類中是不能直接給private中的類成員賦值的,所以就靠構造函數,不過要注意有參構造和無參構造,默認都是無參的,比如你A a(1, 3)這樣的就不對了 除非你在類中寫一個帶參數的構造函數。
當函數調用結束的時候,會自動調用析構函數,比如你在clsaa A { public:Add().....},
當你A a; a.Add();後 就自動調用析構,你可以在類中 ~A{cout。。。},你就會發現調用
a.Add() 後就打出你在析構函數中寫的東西,是自動調用的,析構的作用就是釋放對象佔用的資源。以為默認析構什麼也不列印,所以你不會直觀看出析構函數什麼時候執行,自己在析構中加上列印的語言你就會看到了。希望對你能有所幫助
問題四:為什麼說構造方法是一種特殊的方法?構造方法什麼時候執行?被調用? 構造方法沒有返回值,方法名和類名一樣,其作用是用於在NEW一個類的時候,會總先調用這個類的構造方法,構造方法內部可以作一些變數的初始化或在創建這個類時必須調用的一些方法和運算,他是不用特意去調用的方法,會隨著類的創建而自動去調用
例如:我們需要做一個i+j的運算,在這期間我們用到了構造函數,讓其改變了i和j的初始化值
public class Text {
int i = 0;
int j = 0;
/**
* Text 的構造函數 將i和J的值重新初始化賦值
*/
public Text() {
i = 1;
j = 2;
};
public static void main(String[] args) {
Text s = new Text();
此時當你NEW完Text()時程序已經自動執行了Text的構造 函數i和j的值已經是1和2
System.out.println(s.i + s.j);
}
}
問題五:構造函數何時被調用 問法還是有問題的,構造函數包括復制構造函數
對象被創建時構造函數被調用,關鍵詞:創建時,A a; 這種形式,指針類型在new的時候才調用
復制構造函數,也是構造函數,用一個對象作為參數創建另一個對象時,或賦值(同樣關注創建時)
如 A a(b);
A b;
A a = b;
以下的不是調用復制構造函數
A a,b; 默認(無參)構造被調用
a = b; 賦值
問題六:java中的構造方法到底有什麼用?什麼時候採用? 1.如果當用戶沒有定義構造方法時,編譯器會為類自動添加形如類名() { } 的無參構造方法,但是一但自己定義了構造 方法,編譯器將不再自動添加.
也就是說構造方法不是必須有的.如果你之前一直未自定義構造方法,當你new一個對象時,系統會自動調用默認的一個無伐構造方法,給你對象的實例變數賦初值,比如int型默認為0.但一旦你自己定義了構造方法並new一個對象後,你再new一個對象時系統將不再為你自動提供默認的無參構造方法,那麼你必須自己定義一個構造方法,否則編譯出錯
2 構造器可以不只一個,這叫做方法的重載
3.構造方法不但是要給對象的實例變數賦初值,更重要的是還和new一起來創建對象 ,如果你的對象沒有實例變數,當然不用給對象的實例變數賦初值,也就不需要有參的構造器.但這在實際應用中,是毫無意義的.因為沒有實例變數的對象什麼也幹不了.
問題七:java中構造方法(類)有哪些條件,一般什麼時候被調用 構造方法是類中比較特殊的方法、它有如下幾個特點
1.方法沒有返回值
2.方法名和類名相同
3.構造方法可以重載(包括參數類型不同的重載和參數個數不同的重載)
4.每個類默認會有一個無參的構造函數
例:
public Class User{
public User(){}
public User(String name,int age){
this.name = name;
this.age = age;
}
private String name;
private int age;
public String getName(){
return this.name;
}
public void setName(String name){
this.name = name;
}
public int getAge(){
return this.age;
}
public void setAge(int age){
this.age = age;
}
}
構造函數是在你New對象的時候被調用的
例: User user = new User();
問題八:構造方法和析構方法什麼時候被調用 構造函數的作用是保證每個對象的數據成員都有何時的初始值。
析構函數的作用是回收內存和資源,通常用於釋放在構造函數或對象生命期內獲取的資源。
一般我們都知道構造和析構的次序:
構造從類層次的最根處開始,在每一層中,首先調用基類的構造函數,然後調用成員對象的構造函數。析構則嚴格按照與構造相反的次序執行,該次序是唯一的,否則編譯器將無法自動執行析構過程。
構造函數和析構函數都是由編譯器隱式調用的。這些函數的調用順序取決於程序的執行進入和離開實例化對象時所在的那個作用域的順序。一般而言,析構函數的調用順序和構造函數的調用順序相反,但是,對象的存儲類可以改變析構函數的調用順序。
對於在全局作用域中定義的對象,它們的構造函數是在文件中所有其他函數(包括main)開始執行之前被調用的(但無法保證不同文件的全局對象構造函數的執行順序)。對應的析構函數是在終止main之後調用的。
exit函數會迫使程序立即終止,而不會執行自動對象的析構函數。這個函數經常用來在檢測到輸入錯誤或者程序所處理的文件無法打開時終止程序。
abort函數與exit函數功能相似,但它會迫使程序立即終止,而不允許調用任何對象的析構函數。abort函數通常用來表明程序的非正常終止。
自動局部變數的構造函數是在程序的執行到達定義這個對象的位置時調用的,而對應的析構函數是在程序離開這個對象的作用域時調用的(即定義這個對象的代碼完成了執行)。每次執行進入和離開自動對象的作用域時,都會調用它的構造函數和析構函數。如果程序調用了exit或abort函數而終止,則不會調用自動對象的析構函數。
靜態局部對象的析構函數只調用一次,即執行首次到達定義這個對象的位置時。對應的析構函數是在main終止或程序調用exit函數時調用的。
全局對象和靜態對象是以創建它們時相反的順序銷毀的。如果程序由於調用了exit函數而終止,則不會調用靜態對象的析構函數。
下面的demo演示了在幾個作用域不同的存儲類的CreateAndDestory的類的對象,它們的構造函數和析構函數的調用順序。
[cpp] view plain
#include
#include
using namespace std;
class Demo
{
public:
Demo(int,string); 構造函數
~Demo(); 析構函數
private:
int objectID; ID number for object
string message; message describing object
};
Demo::Demo(int ID,string messagestring)
{
objectID = ID; set object's ID number
message = messagestring; set object's descriptive message
cout>
問題九:C++構造函數什麼時候會被調用? Point的構造函數被調唬兩次,你可以這么理解:
當你要構造一個Rect對象的時候,每個Rect對象是不是包含兩個Point對象?
所以這就是為啥構造兩次的原因了。
析構與構造是一樣的,兩次釋放,每個Point分別被析構一次。
3. C語言中如何調用文件中的自定義函數
不知道你用的是什麼開發工具。
用常規開發工具,通常情況下,有以下幾種方法:
1、創建你的文件,include 你要調用的函數所在的文件,然後直接調用;
2、創建一個工程文件,將你所要調用函數的文件載入到工程文件中,然後,在你調用的文件中,聲明你要調用的函數,然後調用即可;
3、將你要調用的函數所在的文件分離,讓其不包含主函數,然後將其單獨編譯,生成obj文件,通過lib將其有obj文件轉換為lib文件,建立單獨的聲明函數頭文件,設置庫文件目錄,在你要調用的文件中include聲明函數頭文件,然後調用即可。
4. 如何用匯編實現C語言函數調用
1。對於「匯編調用」:
我知道你要調用func,而不是它本身,但如果這個函數比較復雜時是必須用逆向先分析func這個函數,然後再確定參數列表和返回值的……
2。對於你的內聯匯編的代碼:
這里到底要不要用add %3, %%rsp;還是一個問題,因為要看函數使用的是什麼調用標准,有標准C的,VB的,Pascal的,包括fastcall,stdcall,cdecl等……
3。對於「知道函數參數的起始地址和長度」:
這個的話,除了參數中有字元數組和直接結構體什麼的,所有的基本變數基本都是每8位元組(64位)一個,並且Intel一般都用bigendian的,也就是說,在內存中 01 02 03 04 05 06 07 08 讀入寄存器後會變為: 0x0807060504030201
所以說對於簡單的函數,用8位元組一個參數來做就好了……
而對於有字元數組什麼的就必須用逆向分析了……
這個……只能進行逆向分析了……
反正你知道了函數的地址和長度……
就是你把編譯為機器碼的程序用反編譯工具翻譯成匯編,然後分析一下就好了,C語言的匯編還是比較簡單……
比如這個函數:
int func(int a, int* b) {
// float要用到CPU的FPU,指令記不得,要查下
// 為了簡單就改為int*
printf("a = %d, b = %d\n", a, *b);
return a;
}
編譯成機器碼後,反編譯,如果不加優化,一般都會這樣:
(假設函數入口地址為0400000h)
sub_0400000:
push rbp
mov rbp,rsp ; C函數參數度取使用堆棧式
; 參數在內存中這樣: |...| a | b | ... |
; 由於是64位,故8位元組對齊
mov rax,[rbp+8] ; rax = *(rbp+8) // 這里就是 rax = a
push rsi
mov rsi,[rbp+16] ; rsi = *(rbp+16) // rsi = b
; 調用C函數都是這樣堆棧式,最後一個參數最先入棧
push [rsi]
push rax
push "a = %d, b = %d\n" ; 這里是便於理解,實際上是push這個字元串常量的指針
call printf ; printf("a = %d, b = %d\n",rax,*rsi)
add rsp,24 ; 平衡堆棧,用了3個參數,要還原3*8=24位元組,但根據函數類型的不同去平衡,像調用VB的函數就不需要平衡堆棧……
; 還原數據
mov rsp,rbp
pop rsi
pop rbp
; 一般返回數據都用rax裝載
mov rax,[rbp+8] ;rax=a
ret ; return rax
想調用未知參數列表的函數就是把以上過程倒過來,看著匯編把C的代碼寫出來……
破解注冊碼什麼也是這樣玩的……
實際上你可以直接用反編譯的軟體,比如IDA,直接自動分析,它反編譯的雖然是匯編,但參數列表還是大部分都顯示的……
但是,當編譯器加優化大部分情況就必須自己分析了,因為:
int func(int a, int* b) {
printf("a = %d, b = %d\n", a, *b);
return a;
}
在優化情況下可能為(直接用寄存器傳遞數據):
sub_040000:
push rdx
mov rdx,rax
push rax
push rbx
push "a = %d, b = %d\n"
call printf
mov rax,rdx
pop rdx
ret
其實像www.pediy.com看雪學院有不少這方面的教程……
5. window內自帶的C語言編譯器怎麼用
1、首先,輸入【#include】。

注意事項:
盡管C語言提供了許多低級處理的功能,但仍然保持著跨平台的特性,以一個標准規格寫出的C語言程序可在包括類似嵌入式處理器以及超級計算機等作業平台的許多計算機平台上進行編譯。
6. windows怎麼編譯.c文件
(1)先用記事本編寫如下所示的代碼,並另存為hello.cpp,假設其保存路徑為
C:\Users\Administrator\Desktop。
#include<iostream>
using namespace std;
int main()
{
cout<<"hello world!"<<endl;
return 0;
}
(2)用記事本寫一段簡單的批處理文件,內容如下所示,在保存文件時選擇另存為,文件名
假設為batch.bat,bat是批處理文件的後綴,保存類型選擇:所有文件(這個尤其需要注意),
假設其保存路徑也是:C:\Users\Administrator\Desktop。
set path=D:\Softwares\en_Visual_Studio2010_Professional_x86_x16-81637\VC\bin
set include=D:\Softwares\en_Visual_Studio2010_Professional_x86_x16-81637\VC\include
set lib=D:\Softwares\en_Visual_Studio2010_Professional_x86_x16-81637\VC\lib
上面批處理文件的第一句話表示設置環境變數,這個也可以通過:計算機/屬性/高級系統設置/
環境變數/用戶變數,把D:\Softwares\en_Visual_Studio2010_Professional_x86_x16-81637\VC\bin
放到path的值里去,記得與之前已有值之間用";"隔開。這個path文件夾是我們裝載VS2010時自
帶的,在設置路徑時要根據自己的安裝路徑進行修改,裡麵包含微軟在Windows下給我們提供的
C/C++編譯器cl.exe程序(編譯器自身也是一個軟體程序,只是它的作用是用來編譯其它的程序),
當然還有link.exe鏈接程序,調用cl時,系統會自動調用link程序(後面將看到我們只用了cl命令就
可以進行C/C++程序的編譯、鏈接)。後面兩句話分別表示包含C++中自帶的頭文件庫和靜態鏈接
庫,靜態理解庫包含了頭文件中函數對應的實現部分,為了不讓人們看到其中的源代碼,它以二進
制文件形式編碼,若要查看其內容需要進行反匯編。
(3)通過cmd命令進入DOS操作界面,輸入cd C:\Users\Administrator\Desktop進入cpp文件和bat
批處理文件所在的位置,然後鍵入batch.bat進行批處理,這些操作在VS2010集成開發環境中都為我
設置好了,所以我們在裡面寫C/C++程序時並沒有這樣設置路徑的繁瑣操作,但是通過自己手動的
路徑設置,我們會對程序的編譯、鏈接、執行有更加深入的認識。
(4)鍵入cl hello.cpp,我們會看到計算機報出了「無法啟動此程序,因為計算機中丟失mspdb100.dll。
嘗試重新安裝該程序以解決此問題」的系統儲物,dll文件是動態鏈接庫文件,其是在cl.exe程序運行時
才被載入進來的文件,這個靜態鏈接庫lib文件不同。這說明在D:\Softwares\en_Visual_Studio2010_
Professional_x86_x16-81637\VC\bin路徑里沒有找到mspdb100.dll,原來此文件在文件夾D:\Softwares\
en_Visual_Studio2010_Professional_x86_x16-81637\VC\Common7\IDE里,我們可以將此文件拷到bin
文件夾里,或將D:\Softwares\en_Visual_Studio2010_Professional_x86_x16-81637\Common7\IDE加到
批處理的path環境變數里,或者將其加到cpp文件所在的文件夾里,這只會引起在搜索順序上的不同。
(5)再次鍵入cl hello.cpp,我們看到在C:\Users\Administrator\Desktop文件夾里得到了hello.obj文件,
這是編譯後的輸出文件,但是沒有得到可執行exe文件,DOS界面里出現這樣的錯誤「LINK:fatal error LNK
1104:cannot open file 'kernel32.lib' 「這樣的鏈接錯誤,kernel32.lib是Windows系統文件,通過Windows
自帶的搜索工具,我們看到此文件在文件夾C:\Program Files\Microsoft SDKs\Windows\v7.0A\Lib里,我們
可以將其加到cpp文件所在的文件夾或bin文件里。再次鍵入cl hello.cpp,我們發現這次程序被成功編譯鏈接
了,cpp文件所在的文件夾里多了兩個文件:hello.obj和hello.exe。
(6)在DOS界面鍵入hello.exe,程序被執行,輸出了我們預想的hello world!,至此,在Windows下模擬
linux命令行操作,編譯C/C++文件全部完成了。
7. c語言的簡單問題
首先確定你們老師建的文件是「c-file」還是「c-file.cpp」
給你提供一個無腦的方法吧:
新建文本文檔,命名"1.txt",然後把這個文本文檔改為「1.cpp」,然後雙擊這個文件,通常是默認用VC等編譯器打開的。
在1.cpp里添加語句include"c-flie.cpp"(如果他建的文件是「c-file.cpp」)
在1.cpp里編寫你的代碼和main函數等等
然後編譯一下1.cpp這個文件就可以了
通常情況下沒有main函數是沒法編譯的,除非有的系統自動調用main,比如(MFC)這類東西;
8. c語言怎麼調用dll文件
1、新建DLLTest文件夾,在該文件夾中新建source文件夾。

注意事項:
C語言能以簡易的方式編譯、處理低級存儲器。C語言是僅產生少量的機器語言以及不需要任何運行環境支持便能運行的高效率程序設計語言。
9. vc2010怎麼進行c語言編譯
1,在windows桌面中Visual Studio打開軟體並新建項目。

10. 函數C.一個類中可以有多個構造函數,多個析構函數
說法正確。
析構函數是自動調用的,不存在重載的可能,所以只有一個析構。
而構造和賦值,可以根據傳入參數進行重載,所以可以有多個。
