程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> 深入研究C語言 第一篇,深入研究第一篇

深入研究C語言 第一篇,深入研究第一篇

編輯:關於C語言

深入研究C語言 第一篇,深入研究第一篇


一. 研究過程

1.第一章:創建編譯環境:

我們首先下載TC2.0,找到其中與編譯連接相關的程序和文件:

(1) 編譯器:TCC.exe

(2) 連接器:tllike.exe

(3) 相關文件:c0s.obj、cs.lib、emu.lib、maths.lib

將文件放在C:\C目錄下。

編寫程序測試我們的編譯環境:

在這裡我們看到,程序被正常的編譯。生成了.exe文件。並且可以正確執行。

當然,在TC中,c0s.obj、cs.lib、emu.lib、maths.lib這四個文件時在TC目錄下的lib文件夾下,但是我們如果將lib文件夾直接放入C:\C目錄下,程序在編譯的時候會提示:

C0s.obj:Unable to open file

這是因為,TCC沒有找到lib目錄下的c0s.obj文件,我們可以推知,TCC默認在尋找文件的時候只在自己同層的目錄下尋找。

在這裡我們發現,我們只用了TCC,並沒有用到TLINK。那TLINK的作用是什麼呢?

我們刪除TLINK。然後進行編譯連接的工作。我們看到:

我們看到,TLINK其實是被TCC調用實現功能的。

書中的解釋是:TCC.EXE 將a.c編譯成a.obj

TCC調用TLINK將c0s.obj、cs.lib、emu.lib、maths.lib中的相關代碼連接到一起生成.exe文件。

在剛才的步驟中,雖然我們沒有生成.exe,但是我們發現,生成了1.obj。那麼,我們把TLINK重新找回來,能不能將這個1.obj連接成.exe呢?

我們嘗試:

我們發現我們成功的連接完成。

當我們用TCC編譯時,程序可有兩個最大為64K的段,一個段為代碼段,棧和數據段共用一個段。我們如何來驗證這一點呢?(注:這裡其實是用到了後面的內容)。我們編寫這樣一個程序,讓其顯示程序運行時CS和SS,DS的值。

我們編譯運行,查看結果:

我們發現,CS是一個值,DS,SS兩者值相等。這樣也就驗證了代碼段為一個段,棧和數據段共用一個段。而我們又知道,每個段地址不變,偏移地址從0000-ffff是64K的字節。所以這兩個段的最大值是64K。

另外,我們在CMD中直接輸入TCC,會顯示出TCC的使用參數,如下:

2.第二章:顯示函數的段地址和偏移地址:

我們繼續研究第二章的內容:

在main函數中添加語句,使下面的程序可以打印出所有函數的段地址和偏移地址。

程序如下:

我們最直接的想法是用取地址的方式來查看。我們知道,在C語言中,&的作用是取地址。比如:

運行後結果如下:

那麼,函數是不是也可以這樣來取地址呢?我們嘗試:

在這裡,我們直接加類似&f1這樣的取地址加函數名的形式可以麼?我們分析:在debug中,我們看到子程序調用是都是執行的CALL(地址)的方式。在這裡,函數名和標號有著類似的作用,就是方便編程人員編程、方便編譯器編譯和鏈接。他的本質應該是一個地址值。

我們直接編譯看看是否會報錯,證實我們的猜想。

我們發現沒有報錯。也就說明這裡的函數名確實被翻譯標號或與標號類似的東西。

為了方便查看,我們讓這些地址以16進制的方式顯示出來。結果如下:

那麼我們所找到的值是不是函數的入口地址呢?我們進入debug查看:

我們看到,在01fa中,是我們定義的F1函數中的語句,int a=1;也就是說我們的想法是正確的,在printf中直接取函數的地址輸出是可以的。

但是,我們看到,我們打印出的是函數的偏移地址,段地址如何打印呢?

我們知道,在C語言中,我們可以直接調用一些匯編的寄存器,而在匯編中,CS寄存器記錄的是程序段的段地址,也就是說,我們只要顯示出CS,就可以顯示出程序段的段地址。

我們編寫:

運行後其結果如下:

但是這個結果對不對呢?我們還得從debug中驗證:

我們看到,在Debug中-g運行後的結果與CS的值相同。都是0b3b。這也就說明了程序所顯示就是程序在執行時的程序段地址。

那麼這兩次執行2.exe所顯示的程序段地址為什麼會不同呢?我們知道,第一次我們是直接在cmd中運行的2.exe,程序接受系統調用自己執行。而第二次我們是用debug加載進入系統,然後執行。在debug加載的時候,程序被debug加載到了指定的程序段位置。

二. 附加研究:

在進行研究時,我發現在C語言顯示變量的偏移地址時,不同的變量顯示的地址值是不相同的。

比如,全局變量顯示如下:

局部變量顯示如下:

這個結果讓我疑惑,但是我想起了局部變量和全局變量的區別,又看到了-32這樣的值,我猜想這應該是局部變量記載的是相對位置而不是絕對位置。因為絕對位置不會出現負數。我編寫程序如下:

在debug中,我-g到第二個printf();函數前,也就是顯示出變量a的地址後。

通過當前的SS:SP的值與-28進行計算,查看結果單元,發現:

這個單元內所存放的數就是變量a的值,也就是說這個單元就是變量a的存儲單元。

所以得出結論:在C語言中,全局變量的地址是記錄其存儲單元的偏移地址,而局部變量的地址是記錄其存儲單元與現在棧頂指針的相對位置。

(注解,重要:在這裡後期我在回頭看的時候,發現這裡使用的是%d方式,這很重要。因為地址是FFE4,這是一個十六進制的數,本應該用%f的方式顯示出來。而正是兩種數不同的表達和顯示方式造成了這樣的現象。而非是上面的結論。這裡為了過程的完整而保留了這個問題。在此改正。)

本人想深入研究C語言,推薦該看的書

C語言之父的作品 <<The C Programming Language>> 一定要看
再就是 《C專家編程》《C指針》《C陷阱與缺陷》這些都非常經典
這些看了,就絕對是大牛了!

大一的話,先看第一本就行了
 

深入研究C語言要看什書

The C programming Language是入門的經典,因為Dennis M. Ritchie是c的開發者之一。
不過你要有一定的c基礎,最好是以前有c的基礎,不然不要看。
該書沒有什麼廢話,用實例來介紹c的一些特性。並介紹了一些常規算法。

而且非常薄除去附錄才150頁。可以多看幾遍,我沒看一次都有不同的收獲,它還有配套的習題解答。
那上面的練習都上機編一下,你c基本上就沒什麼問題了,就該去看算法和數據結構了。
編程時候一定要嚴謹,可以參考下各種風格然後選一種貫徹。

後面書基本的各有側重,等你人門以後自然知道自己需要看哪本
 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved