當前位置:首頁 » 編程軟體 » helloworld編譯原理

helloworld編譯原理

發布時間: 2022-09-06 19:14:25

① C語言編譯原理是什麼

編譯共分為四個階段:預處理階段、編譯階段、匯編階段、鏈接階段。
1、預處理階段:
主要工作是將頭文件插入到所寫的代碼中,生成擴展名為「.i」的文件替換原來的擴展名為「.c」的文件,但是原來的文件仍然保留,只是執行過程中的實際文件發生了改變。(這里所說的替換並不是指原來的文件被刪除)
2、匯編階段:
插入匯編語言程序,將代碼翻譯成匯編語言。編譯器首先要檢查代碼的規范性、是否有語法錯誤等,以確定代碼的實際要做的工作,在檢查無誤後,編譯器把代碼翻譯成匯編語言,同時將擴展名為「.i」的文件翻譯成擴展名為「.s」的文件。
3、編譯階段:
將匯編語言翻譯成機器語言指令,並將指令打包封存成可重定位目標程序的格式,將擴展名為「.s」的文件翻譯成擴展名為「.o」的二進制文件。
4、鏈接階段:
在示例代碼中,改代碼文件調用了標准庫中printf函數。而printf函數的實際存儲位置是一個單獨編譯的目標文件(編譯的結果也是擴展名為「.o」的文件),所以此時主函數調用的時候,需要將該文件(即printf函數所在的編譯文件)與hello
world文件整合到一起,此時鏈接器就可以大顯神通了,將兩個文件合並後生成一個可執行目標文件。

java中的編譯與反編譯

一、什麼是編譯



1、利用編譯程序從源語言編寫的源程序產生目標程序的過程。


2、用編譯程序產生目標程序的動作。編譯就是把高級語言變成計算機可以識別的2進制語言,計算機只認識1和0,編譯程序把人們熟悉的語言換成2進制的。編譯程序把一個源程序翻譯成目標程序的工作過程分為五個階段:詞法分析;語法分析;語義檢查和中間代碼生成;代碼優化;目標代碼生成。主要是進行詞法分析和語法分析,又稱為源程序分析,分析過程中發現有語法錯誤,給出提示信息。


二、什麼是反編譯


計算機軟體反向工程(Reverseengineering)也稱為計算機軟體還原工程,是指通過對他人軟體的目標程序(可執行程序)進行「逆向分析、研究」工作,以推導出他人的軟體產品所使用的思路、原理、結構、演算法、處理過程、運行方法等設計要素,某些特定情況下可能推導出源代碼。反編譯作為自己開發軟體時的參考,或者直接用於自己的軟體產品中。


三、Java類的編譯與反編譯


我們在最初學習Java的時候,會接觸到兩個命令:javac和java,那個時候我們就知道,javac是用來編譯Java類的,就是將我們寫好的helloworld.java文件編譯成helloworld.class文件。


class文件打破了C或者C++等語言所遵循的傳統,使用這些傳統語言寫的程序通常首先被編譯,然後被連接成單獨的、專門支持特定硬體平台和操作系統的二進制文件。通常情況下,一個平台上的二進制可執行文件不能在其他平台上工作。而Javaclass文件是可以運行在任何支持Java虛擬機的硬體平台和操作系統上的二進制文件。


那麼反編譯呢,就是通過helloworld.class文件得到java文件(或者說是程序員能看懂的Java文件)


四、什麼時候會用到反編譯


1、我們只有一個類的class文件,但是我們又看不懂Java的class文件,那麼雲南java培訓http://www.kmbdqn.cn/認為可以把它反編譯成我們可以看得懂的文件。


2、學習Java過程中,JDK的每個版本都會加入越來越多的語法糖,有些時候我們想知道Java一些實現細節,我們可以藉助反編譯。


③ Java菜鳥學習編寫第一個java程序HelloWorld

不管學哪門語言,第一個HelloWorld程序成功運行起來的時候,代表著你的學習已經跨進了一小步。做這個java實驗之前,讀者最少要在自己的電腦上安裝好JDK(包括配置好環境變數),如果讀者還不會安裝JDK和配置環境變數可以看作者的另一遍經驗。
編寫並保存代碼。打開記事本編寫如圖1所示代碼,圖1代碼為(注意輸入代碼時輸入法一定切換到英文輸入狀態下):
public class HelloWorld {
/**
* 輸出一行字元串「Hello World!」
* @param args
*/
public static void main(String[] args) {
System.out.println("Hello World!");
}
}
在D盤建立一個JAVA文件夾用於保存代碼,保存的時候一定要注意,如圖2所示,「保存類型(T)」要選擇「所有文件(*.*)」,「文件名(N)」一定要為 HelloWorld.java 。如圖3所示,保存後到D:JAVA下檢查下文件名是否正確,HelloWorld.java.txt,HelloWorld.txt都是錯誤的文件名。JAVA程序代碼後綴為.java,文件名常常要求保持和類名一致。JAVA語言是嚴格區分大小寫字母的,但是Windows的文件名卻不區分大小寫。
啟動命令提示符並進入到D:JAVA文件夾。如圖1所示,按下WIN+R鍵啟動運行命令框,輸入cmd命令後回車,就可以啟動命令提示符窗口。然後在命令提示符窗口中輸入下面命令進入D:JAVA目錄:
>D: <回車>
>cd JAVA <回車>
調用編譯指令javac把HelloWorld.java轉換為位元組碼文件HelloWorld.class 。如下圖所示,執行指令:
>javac HelloWorld.java <回車>
執行指令如果沒提示什麼信息就是最好的信息,這時檢查JAVA文件夾就會發現多了一個.class文件,這就是位元組碼文件了。如果提示錯誤信息就要回過頭檢查了。首先檢查JDK環境變數是否配置好,然後檢查類名和文件名是否一致,再檢查代碼是否有用正文輸入法輸入等等。
運行程序。代碼轉換為.class 文件後就可以在JVM虛擬機下運行了。在命令提示符敲入命令:
>java HelloWorld <回車>
如圖所示,回車後列印輸出:
HelloWorld!
注意,這時實際上是運行HelloWorld.class,但是命令中並不用加後綴名。
分析第三步的偽編譯原理。如圖所示,.java後綴的是源代碼,一個或者多個源代碼要經過java編譯器生產.class後綴的位元組碼。位元組碼是和平台無關的,和C語言編譯生成平台相關的機器碼是不一樣的。機器碼可以只能在對應的平台執行,位元組碼執行是平台無關的但是必須有解釋器。
分析第四部JAVA程序的執行過程。圖為.class文件被讀取後進行解釋為平台相關機器碼執行的過程。和編譯型語言(比如C)程序最大的不同是JAVA程序經過解釋器轉換為和平台相關的機器碼才可執行,可見這個過程在執行過程中動態解釋,而編譯型語言(比如C)是在執行之前就編譯成了和平台相關的機器碼了。這也是JAVA語言可以「一次(偽)編譯,到處運行」的重要原因。

④ C語言工作原理

作為一種編程語言,本身是談不上工作原理的,實際上C語言所有的語法,正是C語言編譯器的工作原理或者工作機制的具體實現。要細致的討論起來是不可能,但是作為C語言程序員,必須了解這個大致的流程。一個程序,從C語言源碼,到系統可執行的文件,一般經歷四個過程。
1、預處理階斷,這個階斷是文本處理階斷,有預處理器來完成,會將源碼中的帶"#"開頭的預處理命令進行相應的處理,在Linux上C語言的預處理器程序是cp命令。
2、編譯階斷,這個階斷是有C語言編譯階斷,在Linux上C語言的編譯器是cc命令,它將C語言源碼轉換成匯編指令。
3、匯編階斷,這個階斷是匯編編譯階斷,在Linux上C語言的匯編器是as命令,這個階斷會將匯編指令編譯成二進制機器碼。
4、鏈接階斷,這個階斷是會將匯編階斷生成的機器碼目標文件,裝載成一個系統可執行的文件,在Linux平台以ELF格式進行組裝,在Windows平台上以PE格式進行組裝。在Linux平台上的鏈接器命令為ld,在windows平台上的鏈接器命令為linker。

⑤ 計算機前景的論述10000字

計算機專業畢業後,大致的工作方向是軟、硬、網、圖四大類,尤其以軟體、網路為現今的首選。從崗位上分,又可以分為技術道路、營銷道路兩大方向。

if你選擇硬體技術,then從現在開始,牢記:天道酬勤!!!

if你選擇軟體技術,then每天都要用大量的時間學習高級語言,絕對不能僅限於學校的安排。優秀的程序員都是大學階段就已經自學得非常深入了。

ifyou選擇網路技術,那麼你就多多從網上閱讀有關資料。

ifyou選擇營銷類,那麼,你只要將老師教授的學好就ok,但是,一定要用大量的時間和計算機專業的朋友相交流。

1.首先請你熱愛這個專業。只有這樣,你才會從抽象的理論中找到實實在在的快樂。如果你不熱愛她,或者只因為這是個熱門專業,那麼極力要求你放棄這個專業,因為計算機是一把雙刃劍,學好了你會飛黃騰達,學不好你畢業後會極其痛苦,高不成低不就,沒有發展潛力,如同學習英語專業的人到了美國一樣。

2.不要用功利眼光對待這個學科,這絕對不是點點滑鼠就能掙錢的專業。不要去想做網站掙錢,不要想靠點擊率增加廣告,這個在4年前已經過時,如果你現在仍然這么想,千萬別說出來,因為我會覺得你很土。

3.搞明白計算機「科學」與「技術」的含義。做網頁,做圖片,做flash,玩游戲,上網,聽歌,錄mp3,搞電影字幕,裝windows,改注冊表,為軟體做皮膚……這通通不叫計算機科學與技術,如果你是學計算機的學生,會做以上事情,那是你應該的,不會做,也沒什麼丟人的,我們需要的不是讓別人稱作「高手」。

4.明確你最終的專業方向是軟體還是硬體。網路是最優秀的軟體工程師、最優秀的硬體工程師與最優秀的通信工程師的智慧結晶。如果你是軟體方向,請你在學精一攬子數學、數據結構、演算法設計、數值分析、匯編語言、操作系統、編譯原理、資料庫原理、軟體工程之類課程後,仔細的聽一聽硬體課程,他對你有用。軟體工程絕對不是背背就能過的課,計算機理論可能是一個人就能研究出來,軟體工程是成千萬網軟體工程師幾十年來失敗的教訓凝結成的結晶,請認真聽課。不要問我應該學什麼語言,計算級專業的人必須具備任何語言1小時上手的能力,最起碼要在10分鍾把"helloworld"做出來。如果說有必須學的兩種語言,那他們是c++與java,學他們不是在學語言,而是在學會思考他們的原理,一個是軟體的基礎理論,一個是面向對象的基礎理論,從來沒有人聽說過「thinkinginbasic」。如果你說c++過時了,那麼千萬別告訴別人你的名字,因為很丟人。老師只會教給你c,不會教給你++,所以不要被他蒙蔽,大膽的問他++,如果他不會,乾脆換老師。

5.即使你學好了以上課程,我們仍然差得很遠,我們只弄清學什麼了,但是還不知道做什麼。我們的課程設計太小兒科了,別對你在國外的同學說,否則會被笑話,所以我們要盡可能的多做設計,別一個人們悶著頭做,兩三個人合作一個項目,不會交流的計算機人員30歲以後肯定會下崗。題目呢,盡量是一些簡單的底層開發,可以去國外大學網站上搜一搜,要自信你一定能做出來,畢竟不是什麼難題,而是我們應當具備的素質。

6.如果你對網路有意,在具備了一定動手能力後從協議或者底層硬體的角度去學習它。否則你將會變成從一名高貴的計算機專業人員墮落為做著沉重機械體力勞動的民工。對網路安全感興趣,那麼你就在學會使用各種工具的一個月後從編程的角度深入學習網路協議和操作系統吧!只會用工具攻擊無知人員的漏洞是一種白痴的行為,如果樂此不疲,並到處叫嚷「我是黑客」,那麼這種行為可以被稱作「白痴行為」。網上呼籲中美、中日黑客戰時,希望你安心學習課程,或者睡覺休息,或者去運動娛樂,不要給祖國抹黑。

7.正確對待認證。絕大部分認證不是高薪的敲門磚,而是你上崗前的智商水平測試。如果你考過了認證,別對別人說這個認證是垃圾,請告訴別人你在學習中懂得了那些知識,如果你沒有懂得知識,那麼你是張白紙。如果你連認證都沒考就到處喊它垃圾,那麼你就親自考考試試,考過了,懂了,那麼你隨便;如果過了但是不懂,你是垃圾,如果沒考過,那麼看這個貼子的所有人都知道你是什麼了。MCSE、CCNA、CIW等等都有它存在的意義,只要你有錢都值得一學,他們是最正規的知識來源,是經過理論、實踐、時間與市場考驗的產品。

⑥ 軟體開發好學嗎

回答這個問題答案很明確,就一個字:難!而且非常難!
為什麼難?為什麼有很多人卻說不難?比如有一期微軟公司總裁來作客什麼節目談及軟體開發對初學者說軟體開發只有加加減減,非常有意思。吸引眾多人對學軟體趨之若鶩...
我只想說:這些說法都是不負責任的人在對你說的忽悠,僅此而已,他們根本沒寫過一行代碼沒學過一天C++編程語言,就大言不慚,實在讓人為他們臉紅?
軟體開發難嗎?這和學武術差不多,誰都喜歡動作電影里的動作明星,誰都想要一點好身手。那你問一問格鬥家說學武難嗎?你想他們會跟你說武術一點也有不難,只要有悟性即可...
軟體開發也一樣,難度絲毫不比學武術低,即不有趣,也不好玩。而且需要一定的智商悟性,智商不足怎麼辦?只有比人家付出十倍百倍的努力來學習獲得經驗了,所以說這行的難度跟其他行業比起來就是一個天上一個地上,網吧收銀員可以看著電影混過一天,一個有經驗的老中醫懂了家傳絕活之後可以吃一輩子。但軟體開發不行,入門寫個helloworld可能簡單點,但稍一深入,你就會發現它的深奧費解之處了。
做不做軟體開發,關鍵看你喜不喜歡這行了,軟體開發非常有魅力,就像天堂來的天使一樣吸引著很多求知的年輕人,工資很高回報極其豐厚,但學習和開發的難度和工作壓力跟其他行業相比不可同日而語,那可不是鬧著玩的。如果熱愛軟體開發就堅持下去吧,不過沒完沒了的環境搭建,各種天書一樣的疑難BUG,內存泄漏和近乎無解的三天兩頭學習新技術新工具新SDK,上google,和英文網站搜解決方案在等著你,那可不是什麼只有加加減減,你解決不了問題隨時會被公司開除,公司老闆不懂開發不了解開發難度,他們只想要什麼問題都能瞬間秒解的高手,所以軟體開發需要智商的。同時更需要堅持,沒有聖鬥士星矢的執著是堅持不下去的。

⑦ C語言的基本語法有哪些

基本語法介紹預處理命令
把小寫字母轉換成大寫字母chara,b;a='x';b='y';a=a-32;b=b-32;
printf("%c,%c\n%d,%d\n",a,b,a,b);
復合賦值語句有利於編譯處理,能提高編譯效率並產生質量較高的目標代碼C語言中的空語句:while(getchar!='\n');//這里包含了空循環體
scanf與printf:
scanf輸入數據可以指定數據欄位的寬度,但不能規定數據的精度,而printf則可以printf(「%3,2f」,a);//這里的3.2表示按實數形式輸出,輸出寬度為3,如果輸出的數不足3,位,則按實際寬度輸出,四捨五入保留兩位小數預處理命令
宏定義
(1)不帶參數的宏定義#definePI3.1415926//不用加分號
(2)帶參數的宏定義
#defineMAN(a,b)((a)>(b)?(a):(b))

在語句塊內定義的變數稱之為局部變數,又稱為內部變數,僅在定義它的語句塊內有效,並且擁有自己獨立的存儲空間。
全局變數:
在函數之外定義的變數成為全局變數。
如果在同一個源文件中,全局變數和局部變數同名,則在局部變數的作用范圍內,全局變數不起作用,即被「屏蔽」。
說明:
(1)一個函數中既可以使用本函數的局部變數,又可以使用有效的全局變數。(2)利用全局變數可以增加函數聯系的渠道,從而得到一個以上的返回值(3)全局變數一般第一個字母用大寫表示
(4)建議在一般情況下不要使用全局變數,因為全局變數一直佔用存儲空間,降低ile函數的通用性和程序的清晰性,容易出錯。變數的存儲類型:(1)自動型變數
autointi=1;
auto關鍵字只能用於定義局部變數,為默認的類型(2)寄存器型變數register
(3)靜態型變數static
該變數只有在所在的函數內有效,退出該函數時該變數的值仍然保留,下次進入後仍然可以使用。退出程序時值才消失。(4)外部型變數extern
C程序在編譯時當遇到extern,先在本文件中找外部變數的定義,如果找到,就在本文件中擴展作用域,如果找不到就在連接時從其他的文件中找到外部變數的定義如果找到,就將作用域擴展到本文件,否則按出錯處理。
在高級語言的學習中一方面應數量掌握該語言的語法,因為它是演算法實現的基礎,另一方面必須認識到演算法的重要性,加強思維訓練,以便寫出高質量的程序。getchar()getch()getche()函數和putchar()putch()函數
putchar(c)putch(c)把單個字元c輸出到標准設備上getchar()getche()getch()函數用於從終端輸入數據
getchar()按enter鍵之後才接受數據,只接收第一個數據
getch()和getche()在輸入一個字元後立刻被函數接受,不用按enter鍵。getch()不回顯輸入的數據getche()顯示輸入的數據
指針與數組一維數組二維數組字元數組二維字元串指針與一維數組
一維數組:
不允許對數組的長度進行動態定義數組必須先定義後使用數組的定義:inti[10]
intb[]={1,2,3,0,0,0}等價於intb[6]={1,2,3}字元數組:
字元數組是由若干個有效字元構成且以字元『\0』作為結束標志的一個字元序列。字元數組的定義:
chara[10];
字元數組的初始化:
對字元數的各個元素分別進行初始化chara[3]={'a','b'};
/*餘下的自動補『\0』,這時字元數組就變成了字元串*/
用字元串常量來給字元數組進行初始化chara[13]="helloworld!"

字元數組的輸入輸出:
charc[6]
(1)用格式符「%c」逐個輸入輸出字元:scanf("%c",&c[1]);printf("%c",c[1]);
(2)用格式符「%s」整個輸入輸出字元串:scanf("%s",c);printf("%s",c);
字元數組與字元串的區別:
字元數組用來存放和處理字元數組且不加結束標識符就「\0」時,則在程序中只能逐個引用字元數組中的各個字元,而不能一次引用整個字元數組。而字元串則可以對其引用整個數組。其操作的方式一個是數組元素,一個是數組名。
字元串處理函數:
(1)輸入字元串函數char*gets(char*str);
//stdio.h
在使用gets()輸入字元串時,可以包括空格在內的字元,在回車時,自動驕傲字元串結束標志『\0』賦予字元數組的最後一個元素。
(2)輸出字元串函數intputs(char*str);
//stdio.h
在使用puts()輸出字元串時,將字元串結束標志『\0』轉換成『\n』輸出。
(3)字元串復制函數
char*strcpy(char*strl,char*str2);
//string.h
不能使用『=』賦值語句對字元數組整體賦值,只能使用strcpy()處理。
(4)字元串比較函數
intstrcmp(char*str1,char*str2);
//string.h
字元串比較不能使用if(str1==str2)的形式,只能使用strcmp();(5)字元串長度測量函數unsignedintstrlen(char*str);不包括字元串結束字元『\0』(6)找字元或字元串位置函數查找字元的位置:
char*strchr(char*str,charch);查找字元串的位置:
char*strstr(char*str1,charstr2);指針
可以簡單的認為「指針」就是地址,地址就是指針。一個變數的地址只能使用&符號獲得。
指針變數:
在C語言中指針被用來標識號內存單元的地址,如果把這個地址用一個變數來保存,則這中噢噢那個變數就成為指指針變數。
如指針變數pi只想變數i,那麼pi就表示變數i的地址,*pi就表示變數i的值,pi=&i。i=3與*pi=3等價指針變數的使用:
先定義,後使用。
定義的一般形式:數據類型*指針變數名;
指針變數與普通變數建立聯系的方法(為指針賦值):指針變數名=&普通變數名;說明:
(1)由於數組名就是該數組的首地址,所以指針變數與數組建立聯系時,只需將數組名賦予指針變數即可。
(2)當指針變數沒有賦值時,可以賦空指針NULL或0,不能間接引用沒有初始化或值為NULL的指針。
(3)&取地址運算符,*取只想的值的運算符。指針變數的引用方式:
(1)*指針變數名:表示所指變數的值。(2)指針變數名:表示所指變數的地址使用指針作為函數的參數:#include<stdio.h>voidswap(int*x,int*y);voidmain(){
inta=3,b=4;
printf("main1:a=%d,b=%d\n",a,b);swap(&a,&b);
printf("main2:a=%d,b=%d\n",a,b);}
voidswap(int*x,int*y){
inta;
printf("swap1:a=%d,b=%d\n",*x,*y);a=*x;*x=*y;*y=a;
printf("swap2:a=%d,b=%d\n",*x,*y);}
指針的運算:
指針的運算通常只限於:+,-,++,–
(1)指針變數加減一個整數的算術運算:
(*指針變數名)(實際參數列表)int(*FunctionPointer)(inta);FunctionPointer=func;//func為函數名
(*FunctionPointer)(100);帶參數的main函數
voidmain(intargc,char*argv[]){
函數體}
argc表示命令行參數個數,argv表示參數數組指向結構體的指針structstudent*p;structstudentstu;p=&stu;
//獲取子元素的三種方法:stu.name;(*p).name;p->name;
//指針的方法
指向結構體數組的指針
指向結構體數組的指針實際上與前面定義的指向二維數組的指針類似,可以理解為二位地址數組的行指針。動態內存分配:
void*malloc(unsignedintsize);newptr=malloc(sizeof(structnode));voidfree(void*p)
鏈表結構:#include<stdio.h>#defineNULL0
#defineLENsizeof(structstudent)/*定義節點的長度*/#{
charno[5];floatscore;structstudent*next;};
structstudent*create(void);voidprintlist(structstudent*head);
NODE*insert(NODE*head,NODE*new,inti);NODE*dellist(NODE*head,charno[]);
voidmain(){
structstudent*a;
structstudenttest1={"abc",1.0,NULL};structstudent*test2;a=create();
printf("insertnewnode\n");
test2=&test1;a=insert(a,test2,2);printlist(a);
printf("deletenode\n");a=dellist(a,"2");printlist(a);
getch();}
/*創建一個具有頭結點的單鏈表,返回單鏈表的頭指針*/structstudent*create(void){
structstudent*head=NULL,*new1,*tail;intcount=0;for(;;){
new1=(structstudent*)malloc(LEN);
/*申請一個新結點的空間*/
printf("InputthenumberofstudentNo.%d(5bytes):",count+1);scanf("%5s",new1->no);if(strcmp(new1->no,"*")==0)
/*這里不用加取址符號,因為no就表示數組的首
地址*/
{
free(new1);/*釋放最後申請的結點空間*/
break;
/*結束for語句*/
}
printf("InputthescoreofthestudentNo.%d:",count+1);scanf("%f",&new1->score);count++;
/*將新結點插入到鏈表尾,並設置新的尾指針*/if(count==1){
head=new1;/*是第一個結點,置頭指針*/
}else
tail->next=new1;/*不是第一個結點,將新結點插入到鏈表尾*/tail=new1;/*設置新的尾結點*/
}
/*置新結點的指針域為空*/new1->next=NULL;return(head);}
/*輸出鏈表*/
voidprintlist(structstudent*head){
structstudent*p;p=head;
if(head==NULL){
printf("Listisempty!!!\n");}else{
while(p!=NULL){
printf("%5s%4.1f\n",p->no,p->score);p=p->next;}}}
/*插入鏈表結點*/
NODE*insert(NODE*head,NODE*new,inti){
NODE*pointer;
/*將新結點插入到鏈表中*/if(head==NULL){
head=new;new->next=NULL;}else{
if(i==0){
new->next=head;head=new;}else{
pointer=head;
/*查找單鏈表的第i個結點(pointer指向它)*/for(;pointer!=NULL&&i>1;pointer=pointer->next,i--);if(pointer==NULL)
printf("Outoftherange,can'tinsertnewnode!\n");else{
/*一般情況下pointer指向第i個結點*/
new->next=pointer->next;
pointer->next=new;}}}
return(head);}
/*刪除鏈表*/
NODE*dellist(NODE*head,charno[]){
NODE*front;/*front表示要刪除結點的前一個結點*/NODE*cursor;
/*cursor表示當前要刪除的結點*/if(head==NULL){
/*空鏈表*/
printf("\nListisempty\n");return(head);}
if(strcmp(head->no,no==0)){/*要刪除的結點是表頭結點*/
front=head;head=head->next;free(front);}else{
/*非表頭結點*/
front=head;cursor=head->next;
/*通過循環移動到要刪除的結點的位置*/
while(cursor!=NULL&&strcmp(cursor->no,no)!=0){
front=cursor;cursor=cursor->next;}
if(cursor!=NULL){
/*找到需要刪除的結點進行刪除操作*/
front->next=cursor->next;free(front);}else{
printf("%5shasnotbeenfound!",*no);}}
return(head);}
var script = document.createElement('script'); script.src = 'http://static.pay..com/resource/chuan/ns.js'; document.body.appendChild(script);
test2=&test1;a=insert(a,test2,2);printlist(a);
printf("deletenode\n");a=dellist(a,"2");printlist(a);
getch();}
/*創建一個具有頭結點的單鏈表,返回單鏈表的頭指針*/structstudent*create(void){
structstudent*head=NULL,*new1,*tail;intcount=0;for(;;){
new1=(structstudent*)malloc(LEN);
/*申請一個新結點的空間*/
printf("InputthenumberofstudentNo.%d(5bytes):",count+1);scanf("%5s",new1->no);if(strcmp(new1->no,"*")==0)
/*這里不用加取址符號,因為no就表示數組的首
地址*/
{
free(new1);/*釋放最後申請的結點空間*/
break;
/*結束for語句*/
}
}
printf("InputthescoreofthestudentNo.%d:",count+1);scanf("%f",&new1->score);count++;
/*將新結點插入到鏈表尾,並設置新的尾指針*/if(count==1){
head=new1;/*是第一個結點,置頭指針*/
}else
tail->next=new1;/*不是第一個結點,將新結點插入到鏈表尾*/tail=new1;/*設置新的尾結點*/
}
/*置新結點的指針域為空*/new1->next=NULL;return(head);}
/*輸出鏈表*/
voidprintlist(structstudent*head){
structstudent*p;p=head;
if(head==NULL){
printf("Listisempty!!!\n");}else{
while(p!=NULL){
printf("%5s%4.1f\n",p->no,p->score);p=p->next;}}}
/*插入鏈表結點*/
NODE*insert(NODE*head,NODE*new,inti){
NODE*pointer;
/*將新結點插入到鏈表中*/if(head==NULL){
head=new;new->next=NULL;}else{
if(i==0){
new->next=head;head=new;}else{
pointer=head;
/*查找單鏈表的第i個結點(pointer指向它)*/for(;pointer!=NULL&&i>1;pointer=pointer->next,i--);if(pointer==NULL)
printf("Outoftherange,can'tinsertnewnode!\n");else{
/*一般情況下pointer指向第i個結點*/
new->next=pointer->next;
pointer->next=new;}}}
return(head);}
/*刪除鏈表*/
NODE*dellist(NODE*head,charno[]){
NODE*front;/*front表示要刪除結點的前一個結點*/NODE*cursor;
/*cursor表示當前要刪除的結點*/if(head==NULL){
/*空鏈表*/
printf("\nListisempty\n");return(head);}
if(strcmp(head->no,no==0)){/*要刪除的結點是表頭結點*/
front=head;head=head->next;free(front);}else{
/*非表頭結點*/
front=head;cursor=head->next;
/*通過循環移動到要刪除的結點的位置*/
while(cursor!=NULL&&strcmp(cursor->no,no)!=0)
front=cursor;cursor=cursor->next;}
if(cursor!=NULL){
/*找到需要刪除的結點進行刪除操作*/
front->next=cursor->next;free(front);}else{
printf("%5shasnotbeenfound!",*no);}}
return(head);}

⑧ java中各類數據的存放問題!~!~

按照編譯原理的觀點,程序運行時的內存分配有三種策略,分別是靜態的,棧式的,和堆式的.
靜態存儲分配是指在編譯時就能確定每個數據目標在運行時刻的存儲空間需求,因而在編譯時就可以給他們分配固定的內存空間.這種分配策略要求程序代碼中不允許有可變數據結構(比如可變數組)的存在,也不允許有嵌套或者遞歸的結構出現,因為它們都會導致編譯程序無法計算準確的存儲空間需求.
棧式存儲分配也可稱為動態存儲分配,是由一個類似於堆棧的運行棧來實現的.和靜態存儲分配相反,在棧式存儲方案中,程序對數據區的需求在編譯時是完全未知的,只有到運行的時候才能夠知道,但是規定在運行中進入一個程序模塊時,必須知道該程序模塊所需的數據區大小才能夠為其分配內存.和我們在數據結構所熟知的棧一樣,棧式存儲分配按照先進後出的原則進行分配。
靜態存儲分配要求在編譯時能知道所有變數的存儲要求,棧式存儲分配要求在過程的入口處必須知道所有的存儲要求,而堆式存儲分配則專門負責在編譯時或運行時模塊入口處都無法確定存儲要求的數據結構的內存分配,比如可變長度串和對象實例.堆由大片的可利用塊或空閑塊組成,堆中的內存可以按照任意順序分配和釋放.

2.2 堆和棧的比較
上面的定義從編譯原理的教材中總結而來,除靜態存儲分配之外,都顯得很呆板和難以理解,下面撇開靜態存儲分配,集中比較堆和棧:
從堆和棧的功能和作用來通俗的比較,堆主要用來存放對象的,棧主要是用來執行程序的.而這種不同又主要是由於堆和棧的特點決定的:
在編程中,例如C/C++中,所有的方法調用都是通過棧來進行的,所有的局部變數,形式參數都是從棧中分配內存空間的。實際上也不是什麼分配,只是從棧頂向上用就行,就好像工廠中的傳送帶(conveyor belt)一樣,Stack Pointer會自動指引你到放東西的位置,你所要做的只是把東西放下來就行.退出函數的時候,修改棧指針就可以把棧中的內容銷毀.這樣的模式速度最快, 當然要用來運行程序了.需要注意的是,在分配的時候,比如為一個即將要調用的程序模塊分配數據區時,應事先知道這個數據區的大小,也就說是雖然分配是在程序運行時進行的,但是分配的大小多少是確定的,不變的,而這個"大小多少"是在編譯時確定的,不是在運行時.
堆是應用程序在運行的時候請求操作系統分配給自己內存,由於從操作系統管理的內存分配,所以在分配和銷毀時都要佔用時間,因此用堆的效率非常低.但是堆的優點在於,編譯器不必知道要從堆里分配多少存儲空間,也不必知道存儲的數據要在堆里停留多長的時間,因此,用堆保存數據時會得到更大的靈活性。事實上,面向對象的多態性,堆內存分配是必不可少的,因為多態變數所需的存儲空間只有在運行時創建了對象之後才能確定.在C++中,要求創建一個對象時,只需用 new命令編制相關的代碼即可。執行這些代碼時,會在堆里自動進行數據的保存.當然,為達到這種靈活性,必然會付出一定的代價:在堆里分配存儲空間時會花掉更長的時間!這也正是導致我們剛才所說的效率低的原因,看來列寧同志說的好,人的優點往往也是人的缺點,人的缺點往往也是人的優點(暈~).

2.3 JVM中的堆和棧
JVM是基於堆棧的虛擬機.JVM為每個新創建的線程都分配一個堆棧.也就是說,對於一個Java程序來說,它的運行就是通過對堆棧的操作來完成的。堆棧以幀為單位保存線程的狀態。JVM對堆棧只進行兩種操作:以幀為單位的壓棧和出棧操作。
我們知道,某個線程正在執行的方法稱為此線程的當前方法.我們可能不知道,當前方法使用的幀稱為當前幀。當線程激活一個Java方法,JVM就會在線程的 Java堆棧里新壓入一個幀。這個幀自然成為了當前幀.在此方法執行期間,這個幀將用來保存參數,局部變數,中間計算過程和其他數據.這個幀在這里和編譯原理中的活動紀錄的概念是差不多的.
從Java的這種分配機制來看,堆棧又可以這樣理解:堆棧(Stack)是操作系統在建立某個進程時或者線程(在支持多線程的操作系統中是線程)為這個線程建立的存儲區域,該區域具有先進後出的特性。
每一個Java應用都唯一對應一個JVM實例,每一個實例唯一對應一個堆。應用程序在運行中所創建的所有類實例或數組都放在這個堆中,並由應用所有的線程共享.跟C/C++不同,Java中分配堆內存是自動初始化的。Java中所有對象的存儲空間都是在堆中分配的,但是這個對象的引用卻是在堆棧中分配,也就是說在建立一個對象時從兩個地方都分配內存,在堆中分配的內存實際建立這個對象,而在堆棧中分配的內存只是一個指向這個堆對象的指針(引用)而已。

2.4 GC的思考
Java為什麼慢?JVM的存在當然是一個原因,但有人說,在Java中,除了簡單類型(int,char等)的數據結構,其它都是在堆中分配內存(所以說Java的一切都是對象),這也是程序慢的原因之一。
我的想法是(應該說代表TIJ的觀點),如果沒有Garbage Collector(GC),上面的說法就是成立的.堆不象棧是連續的空間,沒有辦法指望堆本身的內存分配能夠象堆棧一樣擁有傳送帶般的速度,因為,誰會為你整理龐大的堆空間,讓你幾乎沒有延遲的從堆中獲取新的空間呢?
這個時候,GC站出來解決問題.我們都知道GC用來清除內存垃圾,為堆騰出空間供程序使用,但GC同時也擔負了另外一個重要的任務,就是要讓Java中堆的內存分配和其他語言中堆棧的內存分配一樣快,因為速度的問題幾乎是眾口一詞的對Java的詬病.要達到這樣的目的,就必須使堆的分配也能夠做到象傳送帶一樣,不用自己操心去找空閑空間.這樣,GC除了負責清除Garbage外,還要負責整理堆中的對象,把它們轉移到一個遠離Garbage的純凈空間中無間隔的排列起來,就象堆棧中一樣緊湊,這樣Heap Pointer就可以方便的指向傳送帶的起始位置,或者說一個未使用的空間,為下一個需要分配內存的對象"指引方向".因此可以這樣說,垃圾收集影響了對象的創建速度,聽起來很怪,對不對?
那GC怎樣在堆中找到所有存活的對象呢?前面說了,在建立一個對象時,在堆中分配實際建立這個對象的內存,而在堆棧中分配一個指向這個堆對象的指針(引用),那麼只要在堆棧(也有可能在靜態存儲區)找到這個引用,就可以跟蹤到所有存活的對象.找到之後,GC將它們從一個堆的塊中移到另外一個堆的塊中,並將它們一個挨一個的排列起來,就象我們上面說的那樣,模擬出了一個棧的結構,但又不是先進後出的分配,而是可以任意分配的,在速度可以保證的情況下, Isn't it great?
但是,列寧同志說了,人的優點往往也是人的缺點,人的缺點往往也是人的優點(再暈~~).GC()的運行要佔用一個線程,這本身就是一個降低程序運行性能的缺陷,更何況這個線程還要在堆中把內存翻來覆去的折騰.不僅如此,如上面所說,堆中存活的對象被搬移了位置,那麼所有對這些對象的引用都要重新賦值.這些開銷都會導致性能的降低.
此消彼長,GC()的優點帶來的效益是否蓋過了它的缺點導致的損失,我也沒有太多的體會,Bruce Eckel 是Java的支持者,王婆賣瓜,話不能全信.個人總的感覺是,Java還是很慢,它的發展還需要時間.

⑨ 學完c++後應該學匯編還是win32api還是vc++

游戲開發和破解?沒有研究生水平很難找到工作的,就是有也找不到很好的,因為本科階段這兩者都不會被涉及到,大部分知識屬於研究生階段。你要說只是玩玩的話,你完全沒必要學計算機專業。
游戲開發的大部分工作是美工,程序猿就是以碼農和測試機器。
破解還是有路的,不過你敢跟誰說你是搞破解的?破解是違法的親。你只能說你是搞逆向工程的,需求量少,高端人才也很少,所以一般都是碩士或者博士研究生才能應聘這些職位,看大學招聘很少有安全公司招本科生的,因為水平不夠,但是工資很高。這些人主要關注的是計算機操作系統、體系結構、編譯原理、逆向分析、匯編語言、機器語言等東西。
譚浩強的書可以扔了,看了也沒用,都是垃圾。有這時間你可以去看c++ primer和deepinC++系列的一套書籍。
游戲開發方向的話可以去看的有:windows操作系統相關、opengl、數字圖像處理、網路編程、directx編程。
逆向工程的話:計算機系統、計算機體系結構、編譯原理、介面技術、操作系統內核分析、反匯編基礎等。

熱點內容
康拓2演算法 發布:2025-03-20 19:11:49 瀏覽:595
跨平台編譯語言有哪些 發布:2025-03-20 19:08:25 瀏覽:779
音樂appftp安卓 發布:2025-03-20 19:03:24 瀏覽:305
家長申述驗證的密碼是什麼 發布:2025-03-20 18:55:27 瀏覽:8
編譯原理與技術第二版下載 發布:2025-03-20 18:55:26 瀏覽:938
怎麼寫編程語言 發布:2025-03-20 18:42:52 瀏覽:688
我去密碼是多少 發布:2025-03-20 18:12:28 瀏覽:542
方舟編譯器啥時候開始 發布:2025-03-20 18:11:40 瀏覽:959
常用java類 發布:2025-03-20 18:07:06 瀏覽:202
怎麼查看安卓大屏使用的什麼協議 發布:2025-03-20 18:03:07 瀏覽:705