C語言是一種通用、面向過程的編程語言,具有高效、簡潔、靈活等特點,被廣泛應用于各個領域的軟件開發和系統編程。C語言的誕生可以追溯到20世紀70年代初期,在貝爾實驗室的研究員丹尼斯·里奇(Dennis M. Ritchie)的努力下,C語言逐漸成為了計算機的主要開發語言,并在學術界和工業界得到廣泛的應用。
C語言是一種命令式過程語言,支持結構化編程、詞法變量作用域和遞歸,具有靜態類型系統。從設計上講,C語言的設計目標是提供足夠高級的抽象和結構,接近底層硬件的控制。這使得C語言非常適合于系統級編程和底層開發,能夠直接訪問硬件資源,并具有高效的性能。C語言常用于從最大的超級計算機到最小的微控制器和嵌入式系統等各種計算機架構。
C語言是編程語言B的后繼語言,最初由里奇于1972年至1973年在貝爾實驗室開發,用于構建在Unix上運行的實用程序。在20世紀80年代,C語言逐漸流行起來。時至今日,它已成為使用最廣泛的編程語言之一,幾乎所有現代計算機架構和操作系統都有C編譯器可用。由C語言原設計者合著的《C編程語言》一書,是C語言的首要參考語言規范。20世紀80年代起,由美國國家標準學會(ANSI C)和國際標準化組織(ISO)主要負責對C語言的標準化。
一個遵循標準的C程序,有高可移植性,僅需少量修改,就可在多種計算機平臺和操作系統上進行編譯。此外,C語言具有簡單的語法和豐富的庫函數,為程序員提供了廣泛的功能和靈活的編程方式。
自2000年以來,C語言在衡量編程語言受歡迎程度的TIOBE指數排名中保持在前兩位。
概述
C語言是一種通用的、面向過程式的計算機編程語言,與大多數ALGOL族(ALGOrithmic Language,指令式編程語言族)的大多數過程式編程語言類似。和C++、C#、Java等面向對象編程語言有所不同的是,C語言的設計目標是提供一種能以簡易的方式編譯、處理低級存儲器、僅產生少量的機器碼以及不需要任何運行環境支持便能運行的編程語言。C語言描述問題比匯編語言迅速、工作量小、可讀性好、易于調試、修改和移植,一般只比匯編語言代碼生成的目標程序效率低10%-20%,而代碼質量與匯編語言相當。因此,C語言十分適用于編寫系統級軟件。
從設計細節中來說,C語言采用靜態類型系統和有結構化程序設計的特性,具有變量作用域和遞歸功能。C語言中的可執行代碼包含在子程序(函數)中,其函數參數大多采用值傳遞方式,而數組等特殊數據結構則通過傳遞指針(指向數組第一個元素的地址)來傳遞。
C語言還具有具有以下的特性:
1.基本數據類型包括字符、整型和浮點數等,還有指針、數組、結構和聯合等派生數據類型。
2.變量類型可以轉換,如整數型和字符型變量。
3.可以通過指針對存儲器進行低級控制。
4.不同的變量類型可以組合在一起形成結構體。
5.支持基本的控制流,如條件判斷、循環等。
6.函數可以返回各種數據類型的值,并且可以遞歸調用。
7.C語言目前有44個保留字,允許靈活的變量和函數命名。
8.編譯預處理機制增強了C語言的靈活性。
發展歷史
早期發展
C語言最早由丹尼斯·里奇(Dennis Ritchie)為了在PDP-11電腦上運行的Unix系統所設計出來的編程語言,初次發展在1969年到1973年之間。其起源也與unix操作系統的開發密切相關。它源于BCPL語言,后者由馬丁·理察德(Martin Richards)于1967年左右設計實現。
B語言
1969年,肯·湯普遜(Ken Thompson)為提議在PDP-7上開發一個新的階層式操作系統的計劃,做出了一個分時多任務操作系統,成為第一版UNIX。他希望有一種編程語言來為該平臺開發實用程序。1970年,肯·湯普遜(Ken Thompson)為運行在PDP-7上的首個Unix系統創建了一個最新開發的BCPL系統編程語言的精簡版本(BCPL是一門"無類型"的編程語言:它僅能操作一種數據類型,即機器字/machine word)。當時還沒有BCPL的官方說明,肯修改了語法,使其更加簡潔,這個語言被稱為B語言,它也是無類型的,類似于被稱為SMALGOL的簡化ALGOL。與BCPL一樣,B語言也有一個引導編譯器,以方便移植到新機器上。
因為PDP-7的性能不佳,肯·湯普遜與丹尼斯·里奇決定把第一版unix移植到PDP-11/20的機器上,開發第二版UNIX。但是由于B語言的速度太慢,而且無法利用PDP-11的字節尋址能力等特性,最終用B語言編寫的實用程序寥寥無幾。
新B語言和第一版C語言
1971年,丹尼斯開始改進B語言,以利用功能更強大的PDP-11的特性。一個新增的重要功能是字符數據類型,他稱之為新B語言(NB)。與此同時,肯開始使用NB語言編寫Unix內核,并決定了NB語言的發展方向,于是有了int和char數組。此外,還增加了指針、生成指向其他類型的指針的能力、所有類型的數組以及從函數返回的類型。表達式中的數組變成了指針,并編寫了新的編譯器,語言也更名為C語言。
C語言編譯器和一些實用程序被收錄到第二版Unix中,第二版Unix也被稱為Research Unix。
結構重寫與Unix內核重寫
在艾倫·斯奈德(Alan Snyder)的推動下,同時也是出于業界對BCPL和PL/I中文件包含機制實用性的認可,C語言預處理器于1973年左右被引入第四版Unix,這是C語言第一次應用在操作系統的核心編寫上。此時,C語言已經具備了一些強大的功能,如結構類型(struct)。預處理器的最初版本只提供了包含文件和簡單的字符串替換:無參數宏的#include和#define。此后不久,邁克·萊斯克(Mike Lesk)和約翰·雷澤(John Reiser)等人對其進行了擴展開發,納入了帶參數和條件編譯的宏。
1975年C語言開始移植到其他機器上使用。史蒂芬·強生(Stephen C. Johnson)為C語言實現了一套“可移植編譯器”,這套編譯器修改起來相對容易,并且可以為不同的機器生成代碼。從那時起,C在大多數計算機上被使用,從最小的微型計算機到與CRAY-2超級計算機。當時的C語言很規范,即使沒有一份正式的標準,人們也可以寫出C程序,并且無須修改就可以運行在任何支持C語言和最小運行時環境的計算機上。
由此可知,從發明起C語言就是為系統級編程而設計,程序的運行效率至關重要,因此,C語言與真實機器能力的高度匹配的能力也就不足為奇。
K&R C
1978年,布萊恩·克尼根(Brian Kernighan)和丹尼斯·里奇出版了第一版《C程序設計語言》,該書以作者名字的首字母"K&R"命名,多年來一直是C語言的非正式規范。該書描述的C語言規范版本通常被稱為"K&R C"。該書第二版涵蓋了后來的ANSI C標準。K&R引入了多種語言特性,包括:
因為許多舊的編譯器仍在使用K&R C規范,而且K&R C代碼不與后來的ANSI標準沖突,是合法的標準C代碼,所以即使在1989年ANSI標準發布之后,K&R C仍然被認為是C程序員考慮實現最大可移植性時所采用的基礎規則。在C語言的早期版本中,只有返回類型為int以外的函數才必須在函數定義之前聲明,即未聲明的函數被假定為返回類型為int。下面是一個早期版本C語言函數定義和聲明的實例:
在K&R C語言中,被注釋掉的int類型指定符可以省略,但在后來的標準中卻是必需的。由于K&R函數聲明中不包含任何關于函數參數的信息,因此不進行函數參數類型檢查,不過如果調用本地函數時使用了錯誤的參數個數,或者多次調用外部函數時使用了不同的參數個數或類型,一些編譯器會發出警告信息。人們開發了一些單獨的工具,如unix的lint工具,可以檢查多個源文件中函數使用的一致性。
在該版本的C語言中,大量的擴展、不一致的標準庫、C語言的普及和Unix編譯器不能精確執行K&R 規范等多方面因素,推動了C語言進一步的標準化。
ANSI C和ISO C
在20世紀70年代末和80年代,隨著C語言越來越受歡迎,它的各種版本也被應用在各種大型機、小型機和微型計算機上,包括IBM等大型公司的產品。1983年,美國國家標準學會(American National Standards Institute,簡稱ANSI)成立了一個委員會X3J11,以制定C語言的標準規范。X3J11基于Unix實現制定了C語言標準;然而,Unix C庫的不可移植部分交給了IEEE的1003工作組,這部分也成為1988年POSIX標準的基礎。在1989年,C語言標準被正式通過為ANSI X3.159-1989 "Programming Language C"。這個版本的語言通常被稱為ANSI C,標準C,或C89。
在1990年,ANSI C標準被國際標準化組織(ISO)少量修改后采用為ISO/IEC 9899:1990,有時稱為C90。因此,術語“C89”和“C90”指的是同一個編程語言。同其他國家標準機構一樣,ANSI不再獨立開發C標準,而是轉向國際C標準,由ISO/IEC JTC1/SC22/WG14工作組維護。
C標準化工作的目標是產生K&R C語言的超集,其中還包括許多隨后引入的非官方特性。標準委員會還增加了一些附加功能,如函數原型(借鑒C++)、void指針、對國際字符集和區域設置的支持以及預處理器增強。盡管參數聲明的語法已擴展以包括C++中使用的風格,但K&R標準的接口仍然有效,以便與現有源代碼兼容。具體而言,K&R C語言到ANSI/ISO標準C語言的改進主要包括:
當前的C編譯器的支持C89,并且大多數現代C代碼都是基于它構建的。在沒有依賴硬件的前提下,僅使用標準C編寫的程序,都可以在資源限制范圍內,在所有具有符合C現的平臺上正確運行。但是如果沒有這些限制,如使用了非標準庫(如圖形用戶界面庫,即GUI庫),或依賴于編譯器和平臺特定的屬性(如數據類型的精確大小和端序),程序可能只能在特定的平臺或編譯器上編譯。在必須由符合標準C或基于K&R C的編譯器進行編譯時,可以使用__STDC__宏將代碼分成標準C部分和K&R部分,以防止在基于K&R C的編譯器上使用僅在標準C中可用的功能。
在ANSI/ISO標準化過程之后,C語言規范在幾年內保持相對靜態。僅在1995年對C90標準進行了規范修正(ISO/IEC 9899/AMD1:1995,或稱為C95),糾正了一些細節,并擴大了對國際字符集的支持。
C99
C標準在20世紀90年代末進一步修訂,并于1999年出版ISO/IEC 9899:1999,通常稱為"C99"。此后,它已經通過技術勘誤進行了三次修訂。
C99引入了一些新特性,包括內聯函數、幾種新的數據類型(包括long long int和表示復數的復數類型)、可變長度數組和靈活的數組成員、對IEEE 754浮點數的支持改進、支持可變參數宏,以及以“//”開頭的一行注釋,類似BCPL或C++中的注釋一樣,并且已經在幾個C編譯器中作為擴展實現了。C99在很大程度上與C90向后兼容,但在某些方面更加嚴格,如沒有類型說明符的聲明不再隱式地假定為int。標準宏“__STDC_VERSION__”被定義為值“199901L”,表示支持C99。此外,C99標準要求以轉義字符的形式(例如\u0040或\U0001f431)支持Unicode標識符,并建議支持原始Unicode名稱。
C11
在2007年,對C標準的再一次修訂開始了,被非正式地稱為"C1X"。2011年12月8日,ISO/IEC 9899:2011正式發布。C標準委員會通過了一些基線,對未經測試的新特性進行了限制。此外,C11標準為C和庫添加了許多新特性,包括泛型、匿名結構體、改進的Unicode支持、原子操作、多線程和帶邊界檢查的函數等。它還將現有C99庫的部分內容變為可選,并提高了與C++的兼容性。標準宏“__STDC_VERSION__”被定義為“201112L”,表示支持C11。
C17
C17(也稱為C18)是ISO/IEC 9899:2018的非正式名稱,于2017年編寫并于2018年6月發布,被用來替代C11標準。它沒有引入新的語言特性,只進行了技術修正,對C11中的缺陷進行了補充。標準宏“__STDC_VERSION__”被定義為“201710L”。
C23
C23是下一個C編程語言標準的非正式名稱,很可能成為ISO/IEC 9899:2024,取代C17(標準ISO/IEC 9899:2018)。它在2016年以C2x的形式,預計將于2024年發布。
Embedded C
歷史上,嵌入式C編程需要對C語言進行非標準擴展,以支持定點運算、多個不同內存塊和基本I/O操作等特殊功能。在2008年,C標準委員會發布了一份技術報告,對C語言進行擴展,提供一個共同的標準,以解決這些問題。它包括許多在普通C中不可用的特性,如定點運算、命名地址空間和基本I/O硬件尋址。
技術細節
語法
字符集
基本的C源字符集包括以下字符:
其中,換行表示文本行的結束,它不一定要對應于一個實際的單個字符,但是為了方便起見,C將其視為一個字符。多字節編碼字符可以在字符串文字中使用,但它們不是完全可移植的。基本的C執行字符集包含相同的字符,以及警報、退格和回車等表示,每版C標準修訂版都增加了關于擴展字符集的支持。
保留字
截至C11,有44個保留字,也稱為關鍵字,這些關鍵字是預定義的,除了它們預定用途之外,不能被用于的任何其他目的:
C23將添加14個保留字,并將以前定義一些關鍵字成為備選關鍵字,包括:_Alignas、_Alignof、_Bool、_Static_assert、_Thread_local。
操作符
C語言支持豐富的運算符集,這些運算符是在表達式中使用的符號,用于指定在計算該表達式時要執行的操作。
數據類型
在C編程語言中,數據類型構成了數據元素存儲的語義和特征。它們在語言語法中以內存位置或變量聲明的形式表達。數據類型還決定了數據元素的操作類型或處理方法。C語言提供了基本的運算類型,如整數和實數類型,以及建立數組等語法。
基礎數據類型
主要類型
C語言提供了char、int、float和double四種基本算術類型說明符,以及有符號、無符號、短和長等修飾符。下表列出了在指定大量特定存儲大小聲明時允許的組合。
整數類型的實際大小因實現而異,標準C僅要求數據類型之間的大小關系,以及每個數據類型的最小大小,具體關系要求是:
int類型應該是目標處理器效率最高的整數類型,提供了很大的靈活性。在實際應用中,char通常是8位大小,short通常是16位大小(無符號類型也是如此)。這對于多數平臺都成立,例如1990年代的SunOS 4 Unix、微軟 MS-DOS、現代Linux以及Microchip MCC18用于嵌入式8位PIC微控制器。POSIX要求char的大小也為8位。
標準C中的各種規則使得unsigned char成為用于存儲任意非位字段對象的數組的基本類型。浮點類型(float)的實際大小和行為也因實現而異。唯一的要求是long double不得小于double,double不得小于float。
布爾類型
C99增加了布爾(True/False)類型“_Bool”。此外,
如果unsigned char的大小為8位,變量b的值將為false。這是因為值256不適配布爾數據類型,導致只有它的低8位被使用,從而產生一個零值。不過,改變類型后,之前的代碼就會正常運行:
“_Bool”類型還能確保真值之間恒相等:
結構體
結構體(Structures)將多個可能具有不同數據類型的數據項的存儲匯集到一個由單個變量引用的內存塊中。以下示例聲明了數據類型struct birthday,其中包含了一個人的姓名和生日。結構體定義后,是對變量John的聲明,該變量分配了所需的存儲空間。
結構體的內存布局是由每個平臺的語言實現決定的,但有一些限制:第一個成員的內存地址必須與結構體本身的地址相同;可以使用復合字面量來初始化或分配結構體。函數可以直接返回一個結構體,但是這種方式在運行時通常不太高效。自C99以來,結構體最后一個成員也可以是柔性數組。實際運用中,還常常使用包含指向自身類型的結構體指針的結構體來構建鏈式數據結構:
聯合
聯合類型(Unions)是一種特殊的構造,允許使用不同類型的來訪問同一內存塊。例如,可以聲明一個數據類型的聯合,以允許將相同的數據讀取為整數、浮點數或任何其他用戶聲明的類型。在下面的示例代碼中,聯合u的總大小是u.s的大小——這恰好是u.s.u和u.s.d大小的總和,而且s大于i和f。當將某個值賦給u.i,如果u.i小于u.f,則可能會保留u.f的某些部分。值得注意的是,從聯合中讀取成員與強制轉換不同,因為成員的值不會被轉換,只是被讀取。
枚舉
枚舉(Enumerated)用于定義一組具有離散值的常量,它可以讓數據更簡潔,更易讀。枚舉類型通常用于為程序中的一組相關的常量取名字,以便于程序的可讀性和維護性。定義一個枚舉類型,需要使用enum關鍵字,后面跟著枚舉類型的名稱,以及用大括號{}括起來的一組枚舉常量。每個枚舉常量可以用一個標識符來表示,也可以為它們指定一個整數值,如果沒有指定,那么默認從0開始遞增。它在C語言實現中是以int類型儲存的。舉個例子:
指針
指針(Pointers)是一種數據類型,它包含特定類型變量的存儲位置的地址。每種數據類型T都有一個對應的類型T的指針類型。它們使用星號(*)類型聲明符,在基本存儲類型之后和變量名之前進行聲明。星號前后的空格是可選的。
也可以為指針數據類型聲明指針,從而創建多個間接指針,如char**和int***,包括數組類型的指針。后者不如數組指針常見,其語法也比較容易混淆:
元素pc需要十個內存塊,每個內存塊大小與指向char的指針相同(在多數平臺上通常為40或80字節),但元素pa只有一個指針(大小為4或8字節),它指向的數據是一個十字節數組(sizeof *pa == 10)。
數組
數組(Arrays)是相同類型的值的集合,在內存中連續存儲。除void和函數類型外,每種類型T都可以存在"由N個類型元素組成的數組"類型,即該類型數組。大小為N的數組由從0到N-1(包括N-1)的整數索引。下面是一個簡單的例子:
數組可以多維初始化,但不能賦值。數組將指向第一個元素的指針傳遞給函數。多維數組的定義為數組的數組,除了最外層維度之外,所有維度定義時都必須確定常量大小:
常用庫
C語言使用庫作為其主要的擴展方法。在C語言中,庫是一組包含在單個“存檔”文件中的函數。每個庫通常都有一個頭文件,其中包含庫中包含的函數的原型,并聲明了與這些函數一起使用的特殊數據類型和宏符號。如果程序想要使用庫,必須包含庫的頭文件,并且庫必須與程序鏈接在一起,可以使用編譯器標志來完成鏈接(例如,-lm,縮寫為“鏈接數學庫”)。
最常見的C庫是C標準庫,它由ISO和ANSI C標準指定,并隨每個C實現一起提供(針對嵌入式系統等有限環境的實現可能僅提供標準庫的子集)。C標準庫支持流輸入和輸出、內存分配、數學、字符字符串和時間值。標準頭文件(例如,stdio.h)為這些標準庫的接口規定提供了詳細的說明。
另一個常見的C庫函數集是專門針對Unix和類Unix系統的應用程序使用的,與標準庫有所不同的是提供了與內核接口的函數,在各種標準中有詳細說明(POSIX和Single UNIX規范)。
內存管理
編程語言中最重要的功能之一,是提供管理內存和存儲在內存中的對象的管理。C語言提供了三種主要的方式來為對象分配內存:
這三種方法適用情況不同,具有不同的優缺點。例如,靜態內存分配幾乎沒有分配開銷,自動分配可能會多一些,而動態內存分配在分配和釋放方面都可能都有很大的開銷。靜態對象的持久性有利于在函數調用之間保持狀態信息,自動分配更易于使用,但堆棧空間通常比靜態內存或堆空間更有限且短暫,動態內存分配可以分配一些僅在運行時才知道的對象。
在允許的情況下,自動或靜態分配通常是最簡單的,因為存儲由編譯器管理,減少手動分配和釋放存儲的潛在錯誤,免去了繁瑣的工作。然而,許多數據結構在運行時可能改變大小,由于靜態分配(和C99之前的自動分配)必須在編譯時聲明固定大小,因此有許多情況需要使用動態分配。在未特殊說明時,靜態對象在程序啟動時包含零值或空指針值。但是對于自動和動態分配,只有在明確指定初始值的情況下,對象才會被初始化;否則,它們的值是不確定的(通常是存儲中存在的任意位模式,甚至可能不能表示該類型的有效值)。在這種情況下,如果程序嘗試訪問未初始化的值,則結果是未定義的。
Hello World示例代碼
“Hello,World”示例最早出現在《C程序設計語言》的第一版中,已經成為大多數編程教材中引入程序的范例。這個程序將“hello, world”打印到標準輸出,通過終端或屏幕顯示。一個符合標準的“Hello,World”程序是:
程序的第一行包含一個預處理指令,用#include表示,這個操作使編譯器用tdio.h標準頭文件的整個文本替換該行。該頭文件包含了標準輸入和輸出函數(如printf和scanf)的聲明。尖括號包圍的stdio.h表示可以使用一種搜索策略來定位stdio.h文件,該策略首選編譯器提供的頭文件,而不是其他具有相同名稱的自定義頭文件,與使用雙引號的情況不同。雙引號通常包括本地或項目特定的頭文件。
第三行定義一個名為main的函數。在C程序中,主函數有特殊的用途;運行時環境調用主函數來開始程序執行。類型說明符int表示main函數求值的結果返回給調用者的值是整數。參數列表中的關鍵字void表示此函數不接受任何參數。
大括號的開頭表示開始定義主函數。第五行調用一個名為printf的函數,該函數為系統庫提供。在此調用中,printf函數被提供一個單一參數,即字符串字面值“hello,world\n”中第一個字符的地址。字符串字面值是一個無名的char類型數組,由編譯器自動設置,并帶有一個最終值為“\0”的字符,以標記數組的末尾(以便printf知道字符串的長度)。“\n”是一個轉義序列,C將其翻譯為換行字符,在輸出上表示為當前行的結束。printf函數的返回值是int類型,但由于未使用,因此會被默認丟棄。(更高級的程序可能會檢查返回值以確定printf函數是否成功)。分號“;”表示該語句終止。
大括號的閉合表示主函數代碼的結束。根據C99規范及更高版本,與其他函數不同,主函數在達到終止該函數的“}”時會隱式返回一個值為0的值(C99以前需要顯式的“return 0;”語句)。運行時系統將其理解為成功執行并退出代碼。
應用
系統編程
C語言廣泛用于系統編程,特別是實現操作系統和嵌入式系統應用,比如Linux內核、數據庫管理系統(如SQLite)等等。
網絡開發
歷史上,C語言有時被用于Web開發,作為Web應用程序、服務器和瀏覽器之間信息的“網關”。選擇C語言可能是因為其高速度、強穩定性和強可移植性。但是目前使用C進行的Web開發已不再常見,并且市面上存在許多其他Web開發工具。
其他編程語言
C的廣泛可用性和高效性帶來的一個影響是,許多其他編程語言的編譯器、庫和解釋器通常是用C實現的。例如,Python、Perl、Ruby和PHP等語言的參考實現都是用C編寫的。
參考資料 >
GCC, the GNU Compiler Collection.GNU Project.2023-08-01
Clang: a C language family frontend for LLVM.LLVM.2023-08-01
C language documentation.Microsoft Learn.2023-08-01
Imperative programming: Overview of the oldest programming paradigm.Digital Guide.2023-08-01
TIOBE Index.TIOBE.2023-08-01
History of C.Cppreference.2023-08-04
BCPL to B to C.Lysator.2023-08-04
“A damn stupid thing to do”—the origins of C.Ars Technica.2023-08-04
ANSI C 與 K&R C.北京大學數學科學學院.2023-08-06
C Integrity.International Organization for Standardization.2023-08-06
C99 & Numeric computing.Dr. Dobb's Journal.2023-08-06
ISO/IEC 9899:201x.ISO/IEC.2023-08-06
The Standard.ISO.2023-08-06
TR 18037: Embedded C.ISO / IEC.2023-08-06
ISO/IEC 9899:201x (ISO C11) Committee Draft.Open Standards.2023-08-07
Revise spelling of keywords, proposal for C23.Open Standards.2023-08-07
The constexpr specifier for object definitions.Open Standards.2023-08-07
Make false and true first-class language features, proposal for C23.Open Standards.2023-08-07
Introduce the nullptr constant.Open Standards.2023-08-07
Not-so-magic - typeof for C.Open Standards.2023-08-07
WG14-N2601 : Annex X - IEC 60559 interchange and extended types.Open Standards.2023-08-07
WR14-N3042 : Introduce the nullptr constant.Open Standards.2023-08-07
ISO/IEC 9899:1999 specification.Open Standards.2023-08-07
C and C++ Integer Limits.Microsoft learn.2023-08-07
64-Bit Programming Models: Why LP64?.What is UNIX?.2023-08-07
Width of an Integer Type.GNU.2023-08-07
程序設計語言.The Linux Kernel Archives.2023-08-07
Features Of SQLite.SQLite.2023-08-07
Using C for CGI Programming.Linux Journal.2023-08-07
Web development in C: crazy? Or crazy like a fox?.Medium.2023-08-07
Extending Python with C or C++.Python.2023-08-07
An overview of the Perl 5 engine.Opensource.2023-08-07
To Ruby From C and C++.Ruby.2023-08-07
What is PHP? How to Write Your First PHP Program.freecodecamp.2023-08-07