1. 程式人生 > 實用技巧 >《C和指標》閱讀筆記(2)

《C和指標》閱讀筆記(2)

《C和指標》第二章的內容也非常簡單,主要介紹了程式的編譯過程和詞法規則。個人認為對於初學者來說,可能編譯過程能難於理解一些,所以本文會對編譯過程再擴充套件一下,幫助理解;同時,也擴充套件一點關於C標準發展的timeline。關於詞法規則的內容,理解上沒有什麼難度,多熟悉多使用,就慢慢的記住了。

文章目錄

C標準

本書中會經常出現K&R CANSI C,它們表示什麼意思呢?就涉及到C語言標準的一些歷史,在這裡也簡單介紹一下。

K&R C

1978年,Dennis MacAlistair Ritchie和Brian W. Kernighan一起出版了The C Programming Language,1989年,這哥倆進一步完善,出版了The C Programming Language,Second Edition。Dennis MacAlistair Ritchie被人們稱作C語言之父。所以,The C Programming Language一書中使用的C語言標準也就叫做K&R C。即取了兩位作者的名字的首字母。

ANSI C(C89)

ANSI(American National Standards Institute),美國國家標準協會,成立於1918年。這個機構誕生的原因就是沒有統一標準而使許多企業和技術團隊存在各種矛盾和問題。

ANSI C,就是該協會制訂的關於C語言的標準。1983 年, ANSI委任 X3J11 委員會對 C語言 進行標準化。 經過長期艱苦的過程, 該委員會的工作於 1989 年 12 月 14 日正式被批准為ANSI X3.159-1989 並於 1990 年春天頒佈。這個版本的C語言標準通常被稱為ANSI C,也簡稱為C89

我們知道ANSI只是美國的一個標準化組織,但是並沒有一個機構來完成全球範圍內的標準化工作。於是,1946年10月,25個國家標準化機構的代表在倫敦召開大會,決定成立新的國際標準化機構,定名為ISO(International Organization for Standardization)。中國於1978年加入ISO,在2008年10月的第31屆國際化標準組織大會上,中國正式成為ISO的[常任理事國。(PS:可以看出中國在技術上起步晚,相較於美國晚了90年,被人卡脖子也是意料之中,但中國的科學家、工程師正在奮起直追) ISO是一個國際性的非政府組織,ISO來源於希臘語"ISOS",即"EQUAL"平等之意。

C90

1990年,ANSI C標準(帶有一些小改動)被美國國家標準協會採納為ISO/IEC 9899:1990。這個版本有時候稱為C90

C99

2000年3月,國際標準化組織(ISO)和國際電工委員會(IEC)採納了C語言標準第二版,叫ISO/IEC 9899:1999,簡稱C99標準。

C11

2011年12月,國際標準化組織(ISO)和國際電工委員會(IEC)採納了C語言標準第三版,叫ISO/IEC 9899:2011,簡稱C11標準。

兩種環境

在C語言中,通常存在兩種不同的環境:編譯環境和執行環境。有時候編譯環境和執行環境是相同的,有時候編譯環境和執行環境是不同的。例如,在伺服器後端開發時,編譯和執行都是在伺服器上,所以兩種環境相同;在嵌入式開發中,通常編譯是在X86機器上使用交叉編譯器來完成程式的編譯,而程式的執行是在目標裝置上完成。

編譯

《C和指標》閱讀筆記(1)一文中提到了預處理的概念。第二章又著重介紹了程式的編譯過程,這裡我就再稍微展開一下,進一步的介紹編譯過程到底做了什麼工作。而我們常說的程式的"編譯"是一種代稱,有時候也叫構建(build)。(PS:我個人認為將整個過程表述為構建,更好一些,不至於混淆,但是如果聽到別人說"編譯"時,也要知道它表達的是整個過程)實際上程式的構建主要分為4個步驟,預處理(preprocessing)、編譯(compilation)、彙編(assembly)、連結(linking)。

預處理(preprocessing)

預處理是由前處理器(preprocessor)來完成的。預處理過程主要由前處理器來解釋原始碼中以"#"開頭的預處理指令。例如,#include,#define,#if,#pragma等等。通常使用gcc -E test.c -o test.i來完成預處理動作。

小技巧

當無法判斷巨集定義是否正確或這標頭檔案包含是否正確時,可以通過預處理來更加直觀的確認

編譯(compilation)

編譯是由編譯器(compiler)來完成的。編譯過程只要是把預處理後的檔案(*.i)進行一系列的詞法分析、語法分析、語義分析及優化後生成相應的彙編檔案(*.s,*.S)。所以編譯是整個構建過程中最複雜的一個環節,這裡就不再展開,有機會再單獨介紹編譯更細節的過程。通常使用gcc -S hello.i -o hello.s來完成編譯。可以使用cc1 hello.c

在這裡插入圖片描述

彙編(assembly)

彙編是由彙編器(assembler)來完成的。彙編過程就是將彙編程式碼轉換成機器可執行的指令,經過預處理、編譯、彙編後輸出的檔案就是目標檔案(object file)。通常使用gcc -c hello.s -o hello.o,也可以使用as hello.s -o hello.o

連結(linking)

連結是由連結器(linker)來完成的。連結過程就是將目標檔案以及庫檔案(動態庫、靜態庫)連結起來生成可執行檔案。通常使用gcc hello.o -lpthread -o hello,也可以使用ld hello.o -lpthread -o hello

通常我們可以直接使用gcc命令直接生產可執行檔案,而不需要分步,例如,gcc hello.c -lpthread -o hello。細心的讀者可能發現我也介紹了cc1asld,目的就是為了說明一下,平常我們看到的gcc命令只不過是這些子命令的封裝,gcc 通過不同引數的指定可以只做部分過程,或者完整這個構建過程。

好了,第二章的閱讀就到此了。

關注我

我的公眾號二維碼,歡迎關注
在這裡插入圖片描述

QQ討論群:679603305
在這裡插入圖片描述