這一章依舊會嘮叨很多,才會涉及到代碼
首先得知道編程是什麼
為了減少篇幅,我儘量說的簡單
計算機主要有兩個作用,一是存儲,而是計算,科學家們最早也是因為這兩個原因而發展出計算機原理,而發明計算機的。
計算機和人類交互是通過其輸入輸出設備,正如人類和人類交互,也是通過說話和聽話。我們將計算機抽象的看成是通過CPU進行讀取輸入,進行計算,進行輸出的機器。而這裡的輸入和輸出的地方暫時看成內存。計算則是一些基礎的計算和用他們組合進行的計算。
計算機進行基礎計算的原理是通過對二進制數進行邏輯運算轉換成某種基礎計算機的結果,複雜計算則是將基礎運算混合起來實現的。
計算機在執行計算前必須先知道它到底要計算什麼,因此需要外部設備給其提供指令,計算機進行執行。計算機的主要指令除了知道要怎麼計算以外,還要知道需要計算什麼。這個就得靠輸入了,計算機會從內存裡讀取數據,這個數據的位置會在之前的指令中告知。讀取完成之後,計算機會將數據進行運算,將結果輸出到內存中。當然,指令不只是可以讓計算機計算,還可以讓計算機繼續執行存儲在內存中的一個指令。
因為本文不涉及計算機底層原理,所以不詳細講述,感興趣可以閱讀數字電子技術和計算機組成原理相關書籍。
藉此,如果想要讓計算機執行相關的計算並得到結果,我們就要:給其提供指令,給其提供輸入,接收其輸出,這便是編程所做的事情。
編程的目的是讓我們能夠通過相應的輸入,得到需要的輸出。
由於計算機中的數據都是通過二進制表示和計算的,所以編程需要提供一些特定的二進制數據,指令因為要儲存在內存中,也需要是二進制的數據。所以最早期的編程是通過輸入很多的二進制代碼來進行的,這樣不僅可讀性差,複雜,而且容易出錯。
於是科學家想到了,可以把指令寫成助記詞,這樣進行編程後,再轉換成二進制的數據,於是就有了彙編語言。不同的CPU因為設計原理不同和實現的功能不同,其彙編指令也不一樣,但是為了保證兼容,不同的CPU會遵守一個通用的指令規範,成為指令集,也就是架構。網上有時能看到有人討論x86架構和arm架構,它們是目前最常用的指令集。
實際上因為生產CPU的公司,CPU的設計方式,CPU的適用範圍等一系列原因,產生了數不清的架構,不同架構的彙編是不能夠通用的,那怎麼辦?
正在開發Unix操作系統的丹尼斯也思考了這個問題,於是他想到可以用一門脫離架構的通用編程語言進行開發,然後將其翻譯成彙編,最終翻譯成二進制,這樣只需要寫一個翻譯軟件,就能讓同一份代碼在不同的設備運行。這個語言便是C語言,丹尼斯開發了它,這也是為什麼Unix和類Unix都和C語言高度綁定。
C語言不僅跨平臺,而且是一個簡潔的高級語言,在C語言之前其實已經有很多的高級語言了(大多都是進行數學運算而生的),但是C的出現依舊是很震撼的,它不是專門用於數學運算和算法的,而是真正用於計算機。
在Unix上擁有全套的C語言開發工具,我們一一介紹。
首先,最重要的便是將C語言代碼翻譯成二進制的軟件,它叫做編譯器(compiler),在Unix上使用cc指令(C Compiler)進行調用。類Unix上使用cc的開源實現:gcc。當然,C語言現在只是一個標準,任何人都可以實現C語言的編譯器,接下來的教程也將使用一個熱門編譯器:clang,而非gcc(沒事,參數差不多)。
還需要一個編寫C語言代碼的工具,在Unix上可以使用Vi編輯器進行編寫。Vi的開源實現有著名的Vim,Neovim等,我推薦大家用helix,它也是一個開源的Vi編輯器,操作和Vi大差不差,但是打包了很多開箱即用的功能。
如果你寫了很多代碼文件,那麼通過cc指令同時對其編譯就會很困難,而且會很慢(在以前的計算機上會很明顯),cc可以把不同源文件編譯成二進制的中間文件,然後再將他們合併成最終的二進制文件,此時就需要一個工具來指揮編譯。
在Unix上這個工具是make,它根據開發者寫的稱作makefile的文件,將不同的源文件通過指定的線程數量(同時進行的任務的數量)同時編譯,最終合成一個二進制文件。在類Unix系統上,這個工具有個開源替代: GNU make,用法和Unix上的一樣。
這三個是最基礎最主要的,接下來有些次要,不是Unix上的,但是也很重要的東西:
首先就是寫代碼時,可以將一些功能封裝成叫做函數的東西,可以在代碼中調用函數,如果所有的函數調用都完全自己寫,麻煩不說,很有可能寫錯,所以我們需要對其的自動提示和補全,提供這一功能的是語言服務器(lsp),C語言的語言服務器不止一個,我們安裝最主流的clangd即可,helix會自動使用它。
代碼寫多了不可能沒有bug,它可能是一時疏忽大意,也可能是因為某些特殊原因,無論如何想要修復就要改代碼,想改就要知道哪裡的代碼有問題,所以就需要在運行的時候一個一個代碼的運行,這就需要調試器出馬了。主流的調試器有gdb,lldb等,他們分別屬於gcc和clang套件。
代碼進行多次更改的時候不一定改的都是對的,每次更改需要添加說明內容,告知更改的地方,如果改錯了還需要將以前的代碼恢復,重新修改,在多人合作寫代碼的情況下,不同的人完成不同的部分,還需要將他們合併成一個項目。這些麻煩事可以通過一個叫做git的軟件完成。這個軟件是Linux之父Linus寫的代碼管理器。
於是我們需要在termux安裝它們
apt install clang helix make git
湊齊這一套開發工具了。
現在進行helloworld吧。
Vim的操作各位請自行網上查找,這裡不細講。
輸入
hx first.c
創建並進入first.c文件
輸入以下代碼:
#include <stdio.h>
int main(){
printf("hello,world!");
return 0;
}
不要驚慌,我們挨個解釋:
第一行include並不是C語言代碼中的內容,而是給編譯器使用的指令。稱這類指令為預處理指令。其中include的作用是將後面所指文件複製粘貼過來。
第二行到最後一行是寫了main函數的主體。函數在定義時用大括號包裹函數體,即其要執行的指令。C語言程序會默認執行main函數,所以它是一切C程序的入口。
第三行是printf函數,它來自stdio.h這個文件,負責輸出內容。
第四行是返回一個值:0
這裡我們看出C中的函數的功能和計算機一樣,接收一個輸入,進行一些指令,然後輸出。main函數的返回值即是這個程序運行後的返回值,我們可以將這個返回值拿來判斷程序的運行結果。
現在輸入編譯它的指令
clang first.c
輸入ls查看當前目錄會看到多了個a.out文件,它即是編譯出的可執行文件。
運行它會輸出hello world。
現在你已經學會C語言的hello world了