C語言(c(計算機語言))

C語言(計算機程式語言)

c(計算機語言)一般指本詞條

本詞條是多義詞,共22個義項
更多義項 ▼ 收起列表 ▲

C語言是一種較早的程式設計語言,誕生於1972年的貝爾實驗室。1972 年,Dennis Ritchie 設計了C語言,它繼承了B語言的許多思想,並加入了數據類型的概念及其他特性。 儘管C 語言是與 UNIX 作業系統一起被開發出來的,但它不只支持UNIX。C是一種通用(廣泛可用)的程式語言。

程式設計語言實與編譯器是一體的,C編譯器有著名的GCC(GNU Compiler Collection)等。

廣泛套用於底層開發。C語言能以簡易的方式編譯、處理低級存儲器。C語言是僅產生少量的機器語言以及不需要任何運行環境支持便能運行的高效率程式設計語言。儘管C語言提供了許多低級處理的功能,但仍然保持著跨平台的特性,以一個標準規格寫出的C語言程式可在包括類似嵌入式處理器以及超級計算機等作業平台的許多計算機平台上進行編譯。

最新的C語言標準是C23。

基本介紹

簡介,發展歷史,語言特點,主要特點,特有特點,缺點,語言組成,基本構成,關鍵字,語法結構,函式,運算符號,編程開發,編譯器,集成開發環境,示例程式,

簡介

C語言是一門面向過程計算機程式語言,與C++、C#、Java等面向對象程式語言有所不同。C語言的設計目標是提供一種能以簡易的方式編譯、處理低級存儲器、僅產生少量的機器碼以及不需要任何運行環境支持便能運行的程式語言。C語言描述問題比彙編語言迅速、工作量小、可讀性好、易於調試、修改和移植,而代碼質量與彙編語言相當。C語言一般只比彙編語言代碼生成目標程式效率低10%-20%。因此,C語言可以編寫系統軟體。
當前階段,在編程領域中,C語言的運用非常之多,它兼顧了高級語言和彙編語言的優點,相較於其它程式語言具有較大優勢。計算機系統設計以及應用程式編寫是C語言套用的兩大領域。同時,C語言的普適較強,在許多計算機作業系統中都能夠得到適用,且效率顯著。
C語言擁有經過了漫長發展歷史的完整的理論體系,在程式語言中具有舉足輕重的地位。

發展歷史

C語言誕生於美國的貝爾實驗室,由丹尼斯·里奇(Dennis MacAlistair Ritchie)以肯尼斯·藍·湯普森(Kenneth Lane Thompson)設計的B語言為基礎發展而來,在它的主體設計完成後,湯普森和里奇用它完全重寫了UNIX,且隨著UNIX的發展,c語言也得到了不斷的完善。為了利於C語言的全面推廣,許多專家學者和硬體廠商聯合組成了C語言標準委員會,並在之後的1989年,誕生了第一個完備的C標準,簡稱“C89”,也就是“ANSI C”,截至2020年,最新的C語言標準為2018年6月發布的“C18”。
C語言之所以命名為C,是因為C語言源自Ken Thompson發明的B語言,而B語言則源自BCPL語言。
1967年,劍橋大學的Martin Richards對CPL語言進行了簡化,於是產生了BCPL(Basic Combined Programming Language)語言。
20世紀60年代,美國AT&T公司貝爾實驗室(AT&T Bell Laboratories)的研究員肯·湯普森(Kenneth Lane Thompson)閒來無事,手癢難耐,想玩一個他自己編的,模擬在太陽系航行的電子遊戲——Space Travel。他背著老闆,找到了台空閒的小型計算機——PDP-7。但這台電腦沒有作業系統,而遊戲必須使用作業系統的一些功能,於是他著手為PDP-7開發作業系統。後來,這個作業系統被命名為——UNICS(Uniplexed Information and Computing Service)。
1969年,美國貝爾實驗室的Ken Thompson,以BCPL語言為基礎,設計出很簡單且很接近硬體的B語言(取BCPL的首字母),並且用B語言寫了初版UNIX作業系統(叫UNICS)。
1971年,同樣酷愛Space Travel的丹尼斯·里奇為了能早點兒玩上遊戲,加入了湯普森的開發項目,合作開發UNIX。他的主要工作是改造B語言,使其更成熟。
1972年,美國貝爾實驗室的丹尼斯·里奇在B語言的基礎上最終設計出了一種新的語言,他取了BCPL的第二個字母作為這種語言的名字,這就是C語言。
1973年初,C語言的主體完成。湯普森和里奇迫不及待地開始用它完全重寫了UNIX。此時,編程的樂趣使他們已經完全忘記了那個“Space Travel”,一門心思地投入到了UNIX和C語言的開發中。隨著UNIX的發展,C語言自身也在不斷地完善。直到2020年,各種版本的UNIX核心和周邊工具仍然使用C語言作為最主要的開發語言,其中還有不少繼承湯普遜和里奇之手的代碼
在開發中,他們還考慮把UNIX移植到其他類型的計算機上使用。C語言強大的移植性(Portability)在此顯現。機器語言彙編語言都不具有移植性,為x86開發的程式,不可能在Alpha、SPARCARM等機器上運行。而C語言程式則可以使用在任意架構的處理器上,只要那種架構的處理器具有對應的C語言編譯器和庫,然後將C原始碼編譯、連線成目標二進制檔案之後即可在哪種架構的處理器運行。
1977年,丹尼斯·里奇發表了不依賴於具體機器系統的C語言編譯文本《可移植的C語言編譯程式》。
C語言繼續發展,在1982年,很多有識之士和美國國家標準協會ANSI)為了使C語言健康地發展下去,決定成立C標準委員會,建立C語言的標準。委員會由硬體廠商、編譯器及其他軟體工具生產商、軟體設計師、顧問、學術界人士、C語言作者和應用程式員組成。1989年,ANSI發布了第一個完整的C語言標準——ANSI X3.159-1989,簡稱“C89”,不過人們也習慣稱其為“ANSI C”。C89在1990年被國際標準化組織(International Standard Organization,ISO)一字不改地採納,ISO官方給予的名稱為:ISO/IEC 9899,所以ISO/IEC9899:1990也通常被簡稱為“C90”。1999年,在做了一些必要的修正和完善後,ISO發布了新的C語言標準,命名為ISO/IEC 9899:1999,簡稱“C99”。在2011年12月8日,ISO又正式發布了新的標準,稱為ISO/IEC9899:2011,簡稱為“C11”。
2018年6月,ISO發布了ISO/IEC9899:2018,簡稱“C18”(或“C17”)。C18標準沒有引入新的語言特性,只對C11進行了補充與修正。
2022年9月3日,ISO於Open Standards(計算機標準開放組織)網站上發布了新的C語言標準定稿,稱為 ISO/IEC 9899:2023,簡稱“C23”。

語言特點

主要特點

C語言是一種結構化語言,它有著清晰的層次,可按照模組的方式對程式進行編寫,十分有利於程式的調試,且c語言的處理和表現能力都非常的強大,依靠非常全面的運算符和多樣的數據類型,可以輕易完成各種數據結構的構建,通過指針類型更可對記憶體直接定址以及對硬體進行直接操作,因此既能夠用於開發系統程式,也可用於開發套用軟體。通過對C語言進行研究分析,總結出其主要特點如下:
(1)簡潔的語言
C語言包含的各種控制語句僅有9種,關鍵字也只有32個,程式的編寫要求不嚴格且以小寫字母為主,對許多不必要的部分進行了精簡。實際上,語句構成與硬體有關聯的較少,且C語言本身不提供與硬體相關的輸入輸出、檔案管理等功能,如需此類功能,需要通過配合編譯系統所支持的各類庫進行編程,故c語言擁有非常簡潔的編譯系統。
(2)具有結構化的控制語句
C語言是一種結構化的語言,提供的控制語句具有結構化特徵,如for語句、if...else語句和switch語句等。可以用於實現函式的邏輯控制,方便面向過程的程式設計。
(3)豐富的數據類型
C語言包含的數據類型廣泛,不僅包含有傳統的字元型、整型浮點型、數組類型等數據類型,還具有其他程式語言所不具備的數據類型,其中以指針類型數據使用最為靈活,可以通過編程對各種數據結構進行計算。
(4)豐富的運算符
C語言包含34個運算符,它將賦值、括弧等均視作運算符來操作,使C程式的表達式類型和運算符類型均非常豐富。
(5)可對物理地址進行直接操作
C語言允許對硬體記憶體地址進行直接讀寫,以此可以實現彙編語言的主要功能,並可直接操作硬體。C語言不但具備高級語言所具有的良好特性,又包含了許多低級語言的優勢,故在系統軟體編程領域有著廣泛的套用。
(6)代碼具有較好的可移植性
C語言是面向過程的程式語言,用戶只需要關注所被解決問題的本身,而不需要花費過多的精力去了解相關硬體,且針對不同的硬體環境,在用C語言實現相同功能時的代碼基本一致,不需或僅需進行少量改動便可完成移植,這就意味著,對於一台計算機編寫的C程式可以在另一台計算機上輕鬆地運行,從而極大的減少了程式移植的工作強度。
(7)可生成高質量、目標代碼執行效率高的程式
與其他高級語言相比,C語言可以生成高質量和高效率的目標代碼,故通常套用於對代碼質量和執行效率要求較高的嵌入式系統程式的編寫。

特有特點

C語言是普適性最強的一種計算機程式編輯語言,它不僅可以發揮出高級程式語言的功用,還具有彙編語言的優點,因此相對於其它程式語言,它具有自己獨特的特點。具體體現為以下三個方面:
其一,廣泛性。C語言的運算範圍的大小直接決定了其優劣性。C語言中包含了34種運算符,因此運算範圍要超出許多其它語言,此外其運算結果的表達形式也十分豐富。此外,C語言包含了字元型、指針型等多種數據結構形式,因此,更為龐大的數據結構運算它也可以應付。
其二,簡潔性。9類控制語句和32個關鍵字是C語言所具有的基礎特性,使得其在計算機應用程式編寫中具有廣泛的適用性,不僅可以適用廣大編程人員的操作,提高其工作效率,同時還能夠支持高級編程,避免了語言切換的繁瑣。
其三,結構完善。C語言是一種結構化語言,它可以通過組建模組單位的形式實現模組化的應用程式,在系統描述方面具有顯著優勢,同時這一特性也使得它能夠適應多種不同的編程要求,且執行效率高。

缺點

1.C語言的缺點主要表現為數據的封裝性弱,這一點使得C在數據的安全性上有很大缺陷,這也是C和C++的一大區別。
2.C語言的語法限制不太嚴格,對變數的類型約束不嚴格,影響程式的安全性,對數組下標越界不作檢查等。從套用的角度,C語言比其他高級語言較難掌握。也就是說,對用C語言的人,要求對程式設計更熟練一些。

語言組成

基本構成

數據類型
C的數據類型包括:整型shortintlong、long long)、字元型(char)、實型或浮點型單精度float雙精度double)、枚舉類型enum)、數組類型、結構體類型struct)、共用體類型(union)、指針類型和空類型void)。
常量其值不可改變,符號常量名通常用大寫。
變數是以某標識符為名字,其值可以改變的量。標識符是以字母下劃線開頭的一串由字母、數字或下劃線構成的序列,請注意第一個字元必須為字母或下劃線,否則為不合法的變數名。變數在編譯時為其分配相應存儲單元
數組
如果一個變數名後面跟著一個有數字的中括弧,這個聲明就是數組聲明。字元串也是一種數組。它們以ASCII的NULL作為數組的結束。要特別注意的是,中括弧內的索引值是從0算起的。
指針
如果一個變數聲明時在前面使用*號,表明這是個指針型變數。換句話說,該變數存儲一個地址,而*(此處特指單目運算符*,下同。C語言中另有雙目運算符*)則是取內容操作符,意思是取這個記憶體地址里存儲的內容。指針是C語言區別於其他同時代高級語言的主要特徵之一。
指針不僅可以是變數的地址,還可以是數組、數組元素、函式的地址。通過指針作為形式參數可以在函式的調用過程得到一個以上的返回值,不同於return(z)這樣的僅能得到一個返回值。
指針是一把雙刃劍,許多操作可以通過指針自然的表達,但是不正確的或者過分的使用指針又會給程式帶來大量潛在的錯誤。
字元串
C語言的字元串其實就是以'\0'字元結尾的char型數組,使用字元型並不需要引用庫,但是使用字元串就需要C標準庫裡面的一些用於對字元串進行操作的函式。它們不同於字元數組。使用這些函式需要引用頭檔案
檔案輸入/輸出
在C語言中,輸入和輸出是經由標準庫中的一組函式來實現的。在ANSI C中,這些函式被定義在頭檔案;中。
標準輸入/輸出
有三個標準輸入/輸出是標準I/O庫預先定義的:
stdin標準輸入
stderr輸入輸出錯誤
運算
C語言的運算非常靈活,功能十分豐富,運算種類遠多於其它程式設計語言。在表達式方面較其它程式語言更為簡潔,如自加、自減、逗號運算和三目運算使表達式更為簡單,但初學者往往會覺的這種表達式難讀,關鍵原因就是對運算符和運算順序理解不透不全。當多種不同運算組成一個運算表達式,即一個運算式中出現多種運算符時,運算的優先順序和結合規則就會顯得十分重要。

關鍵字

關鍵字又稱為保留字,就是已被C語言本身使用,不能作其它用途使用的字。例如關鍵字不能用作變數名、函式名等標識符
數據類型關鍵字
short:修飾int,短整型數據,可省略被修飾的int。(K&R時期引入)
long:修飾int,長整型數據,可省略被修飾的int。(K&R時期引入)
long long:修飾int,超長整型數據,可省略被修飾的int。(C99標準新增)
signed:修飾整型數據,有符號數據類型。(C89標準新增)
unsigned:修飾整型數據,無符號數據類型。(K&R時期引入)
restrict用於限定和約束指針,並表明指針是訪問一個數據對象的初始且唯一的方式。(C99標準新增)
複雜類型關鍵字
struct結構體聲明。(K&R時期引入)
union:聯合體聲明。(K&R時期引入)
enum:枚舉聲明。(C89標準新增)
typedef:聲明類型別名。(K&R時期引入)
sizeof:得到特定類型或特定類型變數的大小。(K&R時期引入)
inline:內聯函式用於取代定義,會在任何調用它的地方展開。(C99標準新增)
auto:指定為自動變數,由編譯器自動分配及釋放。通常在棧上分配。與static相反。當變數未指定時默認為auto。(K&R時期引入)
static:指定為靜態變數,分配在靜態變數區,修飾函式時,指定函式作用域為檔案內部。(K&R時期引入)
register:指定為暫存器變數,建議編譯器將變數存儲到暫存器中使用,也可以修飾函式形參,建議編譯器通過暫存器而不是堆疊傳遞參數。(K&R時期引入)
extern:指定對應變數為外部變數,即標示變數或者函式的定義在別的檔案中,提示編譯器遇到此變數和函式時在其他模組中尋找其定義。(K&R時期引入)
const:指定變數不可被當前執行緒改變(但有可能被系統或其他執行緒改變)。(C89標準新增)
volatile:指定變數的值有可能會被系統或其他執行緒改變,強制編譯器每次從記憶體中取得該變數的值,阻止編譯器把該變數最佳化成暫存器變數。(C89標準新增)
流程控制關鍵字
跳轉結構
return:用在函式體中,返回特定值(如果是void類型,則不返回函式值)。(K&R時期引入)
continue:結束當前循環,開始下一輪循環。(K&R時期引入)
break:跳出當前循環或switch結構。(K&R時期引入)
goto:無條件跳轉語句。(K&R時期引入)
if:條件語句,後面不需要放分號。(K&R時期引入)
else:條件語句否定分支(與if連用)。(K&R時期引入)
switch:開關語句(多重分支語句)。(K&R時期引入)
case:開關語句中的分支標記,與switch連用。(K&R時期引入)
default:開關語句中的“其他”分支,可選。(K&R時期引入)

語法結構

順序結構的程式設計是最簡單的,只要按照解決問題的順序寫出相應的語句就行,它的執行順序是自上而下,依次執行。
例如:a=3,b=5,現交換a、b的值,這個問題就好像交換兩個杯子裡面的水,這當然要用到第三個杯子,假如第三個杯子是c,那么正確的程式為:c=a;a=b;b=c,執行結果是a=5,b=c=3,如果改變其順序,寫成:a=b;c=a;b=c;則執行結果就變成a=b=c=5,不能達到預期的目的,初學者最容易犯這種錯誤。順序結構可以獨立使用構成一個簡單的完整程式,常見的輸入、計算、輸出三步曲的程式就是順序結構,例如計算圓的面積,其程式的語句順序就是輸入圓的半徑r,計算s=3.14159*r*r,輸出圓的面積s。不過大多數情況下順序結構都是作為程式的一部分,與其它結構一起構成一個複雜的程式,例如分支結構中的複合語句循環結構中的循環體等。
順序結構的程式雖然能解決計算、輸出等問題,但不能做判斷再選擇。對於要先做判斷再選擇的問題就要使用選擇結構。選擇結構的執行是依據一定的條件選擇執行路徑,而不是嚴格按照語句出現的物理順序。選擇結構的程式設計方法的關鍵在於構造合適的分支條件和分析程式流程,根據不同的程式流程選擇適當的選擇語句。選擇結構適合於帶有邏輯或關係比較等條件判斷的計算,設計這類程式時往往都要先繪製其程式流程圖,然後根據程式流程寫出源程式,這樣做把程式設計分析與語言分開,使得問題簡單化,易於理解。程式流程圖是根據解題分析所繪製的程式執行流程圖
循環結構
循環結構可以減少源程式重複書寫的工作量,用來描述重複執行某段算法的問題,這是程式設計中最能發揮計算機特長的程式結構,C語言中提供四種循環,即goto循環、while循環、do while循環和for循環。四種循環可以用來處理同一問題,一般情況下它們可以互相代替換,但一般不提倡用goto循環,因為強制改變程式的順序經常會給程式的運行帶來不可預料的錯誤。
特別要注意在循環體內應包含趨於結束的語句(即循環變數值的改變),否則就可能成了一個死循環,這是初學者的一個常見錯誤。
三個循環的異同點:用while和do while循環時,循環變數的初始化的操作應在循環體之前,而for循環一般在語句1中進行的;while循環和for循環都是先判斷表達式,後執行循環體,而do while循環是先執行循環體後判斷表達式,也就是說do while的循環體最少被執行一次,而while循環和for就可能一次都不執行。另外還要注意的是這三種循環都可以用break語句跳出循環,用continue語句結束本次循環,而goto語句與if構成的循環,是不能用break和continue語句進行控制的。
順序結構、分支結構和循環結構並不彼此孤立的,在循環中可以有分支、順序結構,分支中也可以有循環、順序結構,其實不管哪種結構,均可廣義的把它們看成一個語句。在實際編程過程中常將這三種結構相互結合以實現各種算法,設計出相應程式,但是要編程的問題較大,編寫出的程式就往往很長、結構重複多,造成可讀性差,難以理解,解決這個問題的方法是將C程式設計成模組化結構。
具體內容:
for循環
for循環結構是c語言中最具有特色的循環語句,使用最為靈活方便,它的一般形式為:
for(表達式1;表達式2;表達式3)循環體語句。(其中;不能省略)
表達式1為初值表達式,用於在循環開始前為循環變數賦初值。
表達式2是循環控制邏輯表達式,它控制循環執行的條件,決定循環的次數。
表達式3為循環控制變數修改表達式,它使for循環趨向結束。
循環體語句是在循環控制條件成立的情況下被反覆執行的語句。
但是在整個for循環過程中,表達式1隻計算一次,表達式2和表達式3則可能計算多次,也可能一次也不計算。循環體可能多次執行,也可能一次都不執行。
先執行表達式2,然後執行循環結構,最後表達式3,一直這樣循環下去。
for循環語句是c語言種功能最為強大的語句,甚至在一定程度上可以代替其他的循環語句
do
do循環結構,do 1 while(2);的執行順序是1->2->1...循環,2為循環條件。
while
while循環結構,while(1) 2;的執行順序是1->2->1...循環,1為循環條件
以上循環語句,當循環條件表達式為真則繼續循環,為假則跳出循環。

函式

C程式是由一組變數或是函式的外部對象組成的。函式是一個自我包含的完成一定相關功能的執行代碼段。我們可以把函式看成一個“黑盒子”,你只要將數據送進去就能得到結果,而函式內部究竟是如何工作的,外部程式是不知道的。外部程式所知道的僅限於輸入給函式什麼以及函式輸出什麼。函式提供了編製程序的手段,使之容易讀、寫、理解、排除錯誤、修改和維護。
C程式中函式的數目實際上是不限的,如果說有什麼限制的話,那就是,一個C程式中必須至少有一個函式,而且其中必須有一個並且僅有一個以main為名的函式,這個函式稱為主函式,整個程式從這個主函式開始執行。
C語言程式鼓勵和提倡人們把一個大問題劃分成一個個子問題,對應於解決一個子問題編制一個函式,因此,C語言程式一般是由大量的小函式而不是由少量大函式構成的,即所謂“小函式構成大程式”。這樣的好處是讓各部分相互充分獨立,並且任務單一。因而這些充分獨立的小模組也可以作為一種固定規格的小“構件”,用來構成新的大程式。
C語言發展的那么多年來,用C語言開發的系統和程式浩如煙海。在發展的同時也積累了很多能直接使用的庫函式
ANSI C提供了標準C語言庫函式
C語言初學者比較喜歡的Turbo C 2.0提供了400多個運行時函式,每個函式都完成特定的功能,用戶可隨意調用。這些函式總體分成輸入輸出函式、數學函式、字元串和記憶體函式、與BIOSDOS有關的函式、字元螢幕和圖形功能函式、過程控制函式、目錄函式等。
Windows系統所提供的Windows SDK中包含了數千個跟Windows應用程式開發相關的函式。其它作業系統,如Linux,也同樣提供了大量的函式讓應用程式開發人員調用。
作為程式設計師應儘量熟悉目標平台庫函式其功能。這樣才能遊刃有餘地開發特定平台的應用程式。比如作為Windows應用程式的開發者,應儘量熟悉Windows SDK;作為Linux應用程式開發者,應儘量熟悉Linux系統調用和POSIX函式規範。

運算符號

比較特別的是,比特右移(>>)運算符可以是算術(左端補最高有效位)或是邏輯(左端補0)位移。例如,將11100011右移3比特,算術右移後成為11111100,邏輯右移則為00011100。因算術比特右移較適於處理帶負號整數,所以幾乎所有的編譯器都是算術比特右移。
運算符的優先權從高到低大致是:單目運算符算術運算符關係運算符邏輯運算符條件運算符賦值運算符(=)和逗號運算符

編程開發

編譯器

GCC,GNU組織開發的開源免費的編譯器
Clang,開源的BSD協定的基於LLVM的編譯器
Visual C++ :: cl.exe,Microsoft VC++自帶的編譯器

集成開發環境

Code::Blocks,開源免費的C/C++ IDE
Dev-C++,可移植的C/C++IDE
Light Table

示例程式

下面是一個在標準輸出設備(stdout)上,印出"Hello, world!"字元串的簡單程式。類似的程式,通常作為初學程式語言時的第一個程式:
#include <stdio.h>
int main(){
    printf("Hello, World! \n");
    return 0;
}
  1. 程式的第一行#include是預處理器指令,告訴C編譯器在實際編譯之前要包含stdio.h檔案。
  2. 下一行int main()是主函式,程式從這裡開始執行。
  3. 下一行printf(...)是C中另一個可用的函式,會在螢幕上顯示訊息"Hello, World!"。
  4. 下一行return 0;終止main()函式,並返回值0。
#include <stdio.h>
int main(){
void move(int *xa,int *xb);
int a,b;
printf("請輸入兩個數a,b:");
scanf_s("%d,%d",&a,&b);
move(&a,&b);
printf("a=%d,b=%d\n",a,b);
return 0;
}
void move(int *xa,int *xb){
int a;
a=*xa;
*xa=*xb;
*xb=a;
}
1.程式的第三行是對函式的聲明,聲明了一個有兩個指針參數的無返回值函式。由於函式的定義在調用函式處下,所以必須進行聲明。
2.第四行是變數的定義,定義了兩個整型變數
3.第六行輸入兩個數,必須以1,0這樣中間有逗號的方式輸入。把兩個數放入變數a,b內。"&"是取地址運算符
4.第七行調用move函式,將兩個變數的值轉換。
5.main函式後就是move函式的定義。
從這個例子可以看出,指針變數可以獲得更多的返回值,這樣是非常方便的。

相關詞條

熱門詞條

聯絡我們