C語言
出自 MBA智库百科(https://wiki.mbalib.com/)
目錄 |
C語言是一門通用電腦編程語言,應用廣泛。C語言的設計目標是提供一種能以簡易的方式編譯、處理低級存儲器、產生少量的機器碼以及不需要任何運行環境支持便能運行的編程語言。
儘管C語言提供了許多低級處理的功能,但仍然保持著良好跨平臺的特性,以一個標準規格寫出的C語言程式可在許多電腦平臺上進行編譯,甚至包含一些嵌入式處理器(單片機或稱MCU)以及超級電腦等作業平臺。
二十世紀八十年代,為了避免各開發廠商用的C語言語法產生差異,由美國國家標準局為C語言訂定了一套完整的國際標準語法,稱為ANSI C,作為C語言最初的標準。
C語言之所以命名為C,是因為 C語言源自Ken Thompson發明的B語言,而 B語言則源自BCPL語言。
1967年,劍橋大學的Martin Richards對CPL語言進行了簡化,於是產生了BCPL(Basic Combined Programming Language)語言。
20世紀60年代,美國AT&T公司貝爾實驗室(AT&T Bell Laboratory)的研究員Ken Thompson閑來無事,手癢難耐,想玩一個他自己編的,模擬在太陽系航行的電子游戲——Space Travel。他背著老闆,找到了台空閑的機器——PDP-7。但這台機器沒有操作系統,而游戲必須使用操作系統的一些功能,於是他著手為PDP-7開發操作系統。後來,這個操作系統被命名為——UNIX。
1970年,美國貝爾實驗室的 Ken Thompson,以BCPL語言為基礎,設計出很簡單且很接近硬體的B語言(取BCPL的首字母)。並且他用B語言寫了第一個UNIX操作系統。
1971年,同樣酷愛Space Travel的Dennis M.Ritchie為了能早點兒玩上游戲,加入了Thompson的開發項目,合作開發UNIX。他的主要工作是改造B語言,使其更成熟。
1972年,美國貝爾實驗室的 D.M.Ritchie 在B語言的基礎上最終設計出了一種新的語言,他取了BCPL的第二個字母作為這種語言的名字,這就是C語言。
1973年初,C語言的主體完成。Thompson和Ritchie迫不及待地開始用它完全重寫了UNIX。此時,編程的樂趣使他們已經完全忘記了那個"Space Travel",一門心思地投入到了UNIX和C語言的開發中。隨著UNIX的發展,C語言自身也在不斷地完善。直到今天,各種版本的UNIX內核和周邊工具仍然使用C語言作為最主要的開發語言,其中還有不少繼承Thompson和Ritchie之手的代碼。
在開發中,他們還考慮把UNIX移植到其他類型的電腦上使用。C語言強大的移植性(Portability)在此顯現。機器語言和彙編語言都不具有移植性,為x86開發的程式,不可能在Alpha,SPARC和ARM等機器上運行。而C語言程式則可以使用在任意架構的處理器上,只要那種架構的處理器具有對應的C語言編譯器和庫,然後將C源代碼編譯、連接成目標二進位文件之後即可運行。
1977年,Dennis M.Ritchie發表了不依賴於具體機器系統的C語言編譯文本《可移植的C語言編譯程式》。
C語言繼續發展,在1982年,很多有識之士和美國國家標準協會為了使這個語言健康地發展下去,決定成立C標準委員會,建立C語言的標準。委員會由硬體廠商,編譯器及其他軟體工具生產商,軟體設計師,顧問,學術界人士,C語言作者和應用程式員組成。1989年,ANSI發佈了第一個完整的C語言標準——ANSI X3.159—1989,簡稱“C89”,不過人們也習慣稱其為“ANSI C”。C89在1990年被國際標準組織ISO(International Organization for Standardization)一字不改地採納,ISO官方給予的名稱為:ISO/IEC 9899,所以ISO/IEC9899: 1990也通常被簡稱為“C90”。1999年,在做了一些必要的修正和完善後,ISO發佈了新的C語言標準,命名為ISO/IEC 9899:1999,簡稱“C99”。在2011年12月8日,ISO又正式發佈了新的標準,稱為ISO/IEC9899: 2011,簡稱為“C11”。
GCC,GNU組織開發的開源免費的編譯器
MinGW,Windows操作系統下的GCC
Clang,開源的BSD協議的基於LLVM的編譯器
Visual C++ :: cl.exe,Microsoft VC++自帶的編譯器
集成開發環境(IDE)
CodeBlocks,開源免費的C/C++ IDE
CodeLite,開源、跨平臺的C/C++集成開發環境
Orwell Dev-C++,可移植的C/C++IDE
C-Free
Light Table
Visual Stdio系列
K&R C
起初,C語言沒有官方標準。1978年由美國電話電報公司(AT&T)貝爾實驗室正式發表了C語言。布萊恩·柯林漢(Brian Kernighan) 和 丹尼斯·里奇(Dennis Ritchie) 出版了一本書,名叫《The C Programming Language》。這本書被 C語言開發者們稱為K&R,很多年來被當作 C語言的非正式的標準說明。人們稱這個版本的 C語言為K&R C。
K&R C主要介紹了以下特色:
結構體(struct)類型
長整數(long int)類型
無符號整數(unsigned int)類型
把運算符=+和=-改為+=和-=。因為=+和=-會使得編譯器不知道使用者要處理i = -10還是i =- 10,使得處理上產生混淆。
即使在後來ANSI C標準被提出的許多年後,K&R C仍然是許多編譯器的最 準要求,許多老舊的編譯器仍然運行K&R C的標準。
ANSI C / C89標準
1970到80年代,C語言被廣泛應用,從大型主機到小型微機,也衍生了C語言的很多不同版本。
1983年,美國國家標準協會(ANSI)成立了一個委員會X3J11,來制定 C語言標準。
1989年,美國國家標準協會(ANSI)通過了C語言標準,被稱為ANSI X3.159-1989 "Programming Language C"。因為這個標準是1989年通過的,所以一般簡稱C89標準。有些人也簡稱ANSI C,因為這個標準是美國國家標準協會(ANSI)發佈的。
1990年,國際標準化組織(ISO)和國際電工委員會(IEC)把C89標准定為C語言的國際標準,命名為ISO/IEC 9899:1990 - Programming languages -- C 。因為此標準是在1990年發佈的,所以有些人把簡稱作C90標準。不過大多數人依然稱之為C89標準,因為此標準與ANSI C89標準完全等同。
1994年,國際標準化組織(ISO)和國際電工委員會(IEC)發佈了C89標準修訂版,名叫ISO/IEC 9899:1990/Cor 1:1994 ,有些人簡稱為C94標準。
1995年,國際標準化組織(ISO)和國際電工委員會(IEC)再次發佈了C89標準修訂版,名叫ISO/IEC 9899:1990/Amd 1:1995 - C Integrity ,有些人簡稱為C95標準。
C99標準
1999年1月,國際標準化組織(ISO)和國際電工委員會(IEC)發佈了C語言的新標準,名叫ISO/IEC 9899:1999 - Programming languages -- C ,簡稱C99標準。這是C語言的第二個官方標準。
在C99中包括的特性有:
增加了對編譯器的限制,比如源程式每行要求至少支持到 4095 位元組,變數名函數名的要求支持到 63 位元組(extern 要求支持到 31)。
增強了預處理功能。例如:
巨集支持取可變參數 #define Macro(...) __VA_ARGS__
使用巨集的時候,允許省略參數,被省略的參數會被擴展成空串。
支持 // 開頭的單行註釋(這個特性實際上在C89的很多編譯器上已經被支持了)
增加了新關鍵字 restrict, inline, _Complex, _Imaginary, _Bool
支持 long long, long double _Complex, float _Complex 等類型
支持不定長的數組,即數組長度可以在運行時決定,比如利用變數作為數組長度。聲明時使用 int a[var] 的形式。不過考慮到效率和實現,不定長數組不能用在全局,或 struct 與 union 里。
變數聲明不必放在語句塊的開頭,for 語句提倡寫成 for(int i=0;i<100;++i) 的形式,即i 只在 for 語句塊內部有效。
允許採用(type_name){xx,xx,xx} 類似於 C++ 的構造函數的形式構造匿名的結構體。
複合字面量:初始化結構的時候允許對特定的元素賦值,形式為:
struct test{int a[3],b;} foo[] = { [0].a = {1}, [1].a = 2 };
struct test{int a, b, c, d;} foo = { .a = 1, .c = 3, 4, .b = 5 }; // 3,4 是對 .c,.d 賦值的
格式化字元串中,利用 \u 支持 unicode 的字元。
支持16進位的浮點數的描述。
printf scanf 的格式化串增加了對 long long int 類型的支持。
浮點數的內部數據描述支持了新標準,可以使用 #pragma 編譯器指令指定。
除了已有的 __line__ __file__ 以外,增加了 __func__ 得到當前的函數名。
允許編譯器化簡非常數的表達式。
修改了 /% 處理負數時的定義,這樣可以給出明確的結果,例如在C89中-22 / 7 = -3, -22% 7 = -1,也可以-22 / 7= -4, -22% 7 = 6。 而C99中明確為 -22 / 7 = -3, -22% 7 = -1,只有一種結果。
取消了函數返回類型預設為 int 的規定。
允許 struct 定義的最後一個數組不指定其長度,寫做 [](flexible array member)。
const const int i 將被當作 const int i 處理。
增加和修改了一些標準頭文件,比如定義 bool 的 <stdbool.h> ,定義一些標準長度的 int 的 <inttypes.h> ,定義複數的 <complex.h> ,定義寬字元的 <wctype.h> ,類似於泛型的數學函數 <tgmath.h>, 浮點數相關的 <fenv.h>。 在<stdarg.h> 增加了 va_copy 用於複製 ... 的參數。里增加了 struct tmx ,對 struct tm 做了擴展。
輸入輸出對寬字元以及長整數等做了相應的支持。
GCC和其它一些商業編譯器支持C99的大部分特性。
C11標準
2011年12月8日,國際標準化組織(ISO)和國際電工委員會(IEC)再次發佈了C語言的新標準,名叫ISO/IEC 9899:2011 - Information technology -- Programming languages -- C ,簡稱C11標準,原名C1X。這是C語言的第三個官方標準,也是C語言的最新標準。
新的標準提高了對C++的兼容性,並增加了一些新的特性。這些新特性包括:
對齊處理(Alignment)的標準化(包括_Alignas標誌符,alignof運算符, aligned_alloc函數以及<stdalign.h>頭文件。
_Noreturn 函數標記,類似於 gcc 的 __attribute__((noreturn))。
_Generic 關鍵字。
多線程(Multithreading)支持,包括:
_Thread_local存儲類型標識符,<threads.h>頭文件,裡面包含了線程的創建和管理函數。
_Atomic類型修飾符和<stdatomic.h>頭文件。
增強的Unicode的支持。基於C Unicode技術報告ISO/IEC TR 19769:2004,增強了對Unicode的支持。包括為UTF-16/UTF-32編碼增加了char16_t和char32_t數據類型,提供了包含unicode字元串轉換函數的頭文件<uchar.h>.
刪除了 gets() 函數,使用一個新的更安全的函數gets_s()替代。
增加了邊界檢查函數介面,定義了新的安全的函數,例如 fopen_s(),strcat_s() 等等。
增加了更多浮點處理巨集。
匿名結構體/聯合體支持。這個在gcc早已存在,C11將其引入標準。
靜態斷言(static assertions),_Static_assert(),在解釋 #if 和 #error 之後被處理。
新的 fopen() 模式,(“…x”)。類似 POSIX 中的 O_CREAT|O_EXCL,在文件鎖中比較常用。
新增 quick_exit() 函數作為第三種終止程式的方式。當 exit()失敗時可以做最少的清理工作。
1、高級語言:它是把高級語言的基本結構和語句與低級語言的實用性結合起來的工作單元。
2、結構式語言:結構式語言的顯著特點是代碼及數據的分隔化,即程式的各個部分除了必要的信息交流外彼此獨立。這種結構化方式可使程式層次清晰,便於使用、維護以及調試。C 語言是以函數形式提供給用戶的,這些函數可方便的調用,並具有多種迴圈、條件語句控製程序流向,從而使程式完全結構化。
4、代碼級別的跨平臺:由於標準的存在,使得幾乎同樣的C代碼可用於多種操作系統,如Windows、DOS、UNIX等等;也適用於多種機型。C語言對編寫需要進行硬體操作的場合,優於其它高級語言。
5、使用指針:可以直接進行靠近硬體的操作,但是C的指針操作不做保護,也給它帶來了很多不安全的因素。C++在這方面做了改進,在保留了指針操作的同時又增強了安全性,受到了一些用戶的支持,但是,由於這些改進增加語言的複雜度,也為另一部分所詬病。Java則吸取了C++的教訓,取消了指針操作,也取消了C++改進中一些備受爭議的地方,在安全性和適合性方面均取得良好的效果,但其本身解釋在虛擬機中運行,運行效率低於C++/C。一般而言,C,C++,java被視為同一系的語言,它們長期占據著程式使用榜的前三名。
C語言是一個有結構化程式設計、具有變數作用域(variable scope)以及遞歸功能的過程式語言。
C語言傳遞參數均是以值傳遞(pass by value),另外也可以傳遞指針(a pointer passed by value)。
不同的變數類型可以用結構體(struct)組合在一起。
只有32個保留字(reserved keywords),使變數、函數命名有更多彈性。
部份的變數類型可以轉換,例如整型和字元型變數。
通過指針(pointer),C語言可以容易的對存儲器進行低級控制。
預編譯處理(preprocessor)讓C語言的編譯更具有彈性。
1、簡潔緊湊、靈活方便
C語言一共只有32個關鍵字,9種控制語句,程式書寫形式自由,區分大小寫。把高級語言的基本結構和語句與低級語言的實用性結合起來。C 語言可以像彙編語言一樣對位、位元組和地址進行操作,而這三者是電腦最基本的工作單元。
2、運算符豐富
C語言的運算符包含的範圍很廣泛,共有34種運算符。C語言把括弧、賦值、強制類型轉換等都作為運算符處理。從而使C語言的運算類型極其豐富,表達式類型多樣化。靈活使用各種運算符可以實現在其它高級語言中難以實現的運算。
3、數據類型豐富
C語言的數據類型有:整型、實型、字元型、數組類型、指針類型、結構體類型、共用體類型等。能用來實現各種複雜的數據結構的運算。並引入了指針概念,使程式效率更高。
4、表達方式靈活實用
C語言提供多種運算符和表達式值的方法,對問題的表達可通過多種途徑獲得,其程式設計更主動、靈活。它語法限制不太嚴格,程式設計自由度大,如對整型量與字元型數據及邏輯型數據可以通用等。
5、允許直接訪問物理地址,對硬體進行操作
由於C語言允許直接訪問物理地址,可以直接對硬體進行操作,因此它既具有高級語言的功能,又具有低級語言的許多功能,能夠像彙編語言一樣對位(bit)、位元組和地址進行操作,而這三者是電腦最基本的工作單元,可用來寫系統軟體。
6、生成目標代碼質量高,程式執行效率高
C語言描述問題比彙編語言迅速,工作量小、可讀性好,易於調試、修改和移植,而代碼質量與彙編語言相當。C語言一般只比彙編程式生成的目標代碼效率低10%~20%。
7、可移植性好
C語言在不同機器上的C編譯程式,86%的代碼是公共的,所以C語言的編譯程式便於移植。在一個環境上用C語言編寫的程式,不改動或稍加改動,就可移植到另一個完全不同的環境中運行。
8、表達力強
C語言有豐富的數據結構和運算符。包含了各種數據結構,如整型、數組類型、指針類型和聯合類型等,用來實現各種數據結構的運算。C語言的運算符有34種,範圍很寬,靈活使用各種運算符可以實現難度極大的運算。
C語言能直接訪問硬體的物理地址,能進行位(bit)操作。兼有高級語言和低級語言的許多優點。
它既可用來編寫系統軟體,又可用來開發應用軟體,已成為一種通用程式設計語言。
另外C語言具有強大的圖形功能,支持多種顯示器和驅動器。且計算功能、邏輯判斷功能強大。
1、C語言的缺點主要表現在數據的封裝性上,這一點使得C在數據的安全性上有很大缺陷,這也是C和C++的一大區別。
2、C語言的語法限制不太嚴格,對變數的類型約束不嚴格,影響程式的安全性,對數組下標越界不作檢查等。從應用的角度,C語言比其他高級語言較難掌握。也就是說,對用C語言的人,要求對程式設計更熟練一些。
1、對齊處理(Alignment)的標準化(包括_Alignas標誌符,alignof運算符,aligned_alloc函數以及<stdalign.h>頭文件)。
2、_Noreturn 函數標記,類似於 gcc 的 __attribute__(noreturn)。
3、_Generic關鍵字。
4、多線程(Multithreading)支持,包括:_Thread_local存儲類型標識符,<threads.h>;頭文件,裡面包含了線程的創建和管理函數。
5、增強的Unicode的支持,基於C Unicode技術報告ISO/IEC TR 19769:2004,增強了對Unicode的支持。包括為UTF-16/UTF-32編碼增加了char16_t和char32_t數據類型,提供了包含unicode字元串轉換函數的頭文件<uchar.h>.
6、刪除了 gets() 函數,使用一個新的更安全的函數gets_s()替代。
7、增加了邊界檢查函數介面,定義了新的安全的函數,例如 fopen_s(),strcat_s()等等。
8、增加了更多浮點處理巨集。
9、匿名結構體/聯合體支持,這個在gcc早已存在,C11將其引入標準。
10、靜態斷言(Static assertions),_Static_assert(),在解釋 #if 和 #error 之後被處理。
11、新的 fopen()模式,(“…x”),類似 POSIX 中的 O_CREAT|O_EXCL,在文件鎖中比較常用。
12、新增 quick_exit()函數作為第三種終止程式的方式。當 exit()失敗時可以做最少的清理工作。
13、_Atomic類型修飾符和<stdatomic.h>頭文件。
(一)數據類型
C的數據類型包括:整型、字元型、實型或浮點型(單精度和雙精度)、枚舉類型、數組類型、結構體類型、共用體類型、指針類型和空類型。
(二)常量與變數
常量其值不可改變,符號常量名通常用大寫。
變數是以某標識符為名字,其值可以改變的量。標識符是以字母或下劃線開頭的一串由字母、數字或下劃線構成的序列,請註意第一個字元必須為字母或下劃線,否則為不合法的變數名。變數在編譯時為其分配相應存儲單元。
(三)數組
如果一個變數名後面跟著一個有數字的中括弧,這個聲明就是數組聲明。字元串也是一種數組。它們以ASCII的NULL作為數組的結束。要特別註意的是,方括內的索引值是從0算起的。[17]
(四)指針
如果一個變數聲明時在前面使用 * 號,表明這是個指針型變數。換句話說,該變數存儲一個地址,而 *(此處特指單目運算符 * ,下同。C語言中另有 雙目運算符 *) 則是取內容操作符,意思是取這個記憶體地址里存儲的內容。指針是 C 語言區別於其他同時代高級語言的主要特征之一。
指針不僅可以是變數的地址,還可以是數組、數組元素、函數的地址。通過指針作為形式參數可以在函數的調用過程得到一個以上的返回值,不同於return(z)這樣的僅能得到一個返回值。
指針是一把雙刃劍,許多操作可以通過指針自然的表達,但是不正確的或者過分的使用指針又會給程式帶來大量潛在的錯誤。
(五)字元串
C語言的字元串其實就是以'\0'字元結尾的char型數組,使用字元型並不需要引用庫,但是使用字元串就需要C標準庫裡面的一些用於對字元串進行操作的函數。它們不同於字元數組。使用這些函數需要引用頭文件<string.h>。
(六)文件輸入/輸出
在C語言中,輸入和輸出是經由標準庫中的一組函數來實現的。在ANSI C中,這些函數被定義在頭文件<stdio.h>;中。
標準輸入/輸出
有三個標準輸入/輸出是標準I/O庫預先定義的:
stdin標準輸入
stdout標準輸出
stderr輸入輸出錯誤
(七)運算
C語言的運算非常靈活,功能十分豐富,運算種類遠多於其它程式設計語言。在表達式方面較其它程式語言更為簡潔,如自加、自減、逗號運算和三目運算使表達式更為簡單,但初學者往往會覺的這種表達式難讀,關鍵原因就是對運算符和運算順序理解不透不全。當多種不同運算組成一個運算表達式,即一個運算式中出現多種運算符時,運算的優先順序和結合規則顯得十分重要。在學習中,對此合理進行分類,找出它們與數學中所學到運算之間的不同點之後,記住這些運算也就不困難了,有些運算符在理解後更會牢記心中,將來用起來得心應手,而有些可暫時放棄不記,等用到時再記不遲。
先要明確運算符按優先順序不同分類,《C程式設計》運算符可分為15種優先順序,從高到低,優先順序為1 ~ 15,除第2.13級和第14級為從右至左結合外,其它都是從左至右結合,它決定同級運算符的運算順序。
關鍵字又稱為保留字,就是已被C語言本身使用,不能作其它用途使用的字。例如關鍵字不能用作變數名、函數名等標識符
由ISO標准定義的C語言關鍵字共32個:
auto double int struct break else long switch
case enum register typedef char extern return union
const float short unsigned continue for signed void
default goto sizeof volatile do if while static inline
restrict _Bool _Complex _Imaginary _Generic[21]
(1)基本數據類型
- void:聲明函數無返回值或無參數,聲明無類型指針,顯示丟棄運算結果。(C89標準新增)
- char:字元型類型數據,屬於整型數據的一種。(K&R時期引入)
- int:整型數據,表示範圍通常為編譯器指定的記憶體位元組長。(K&R時期引入)
- float:單精度浮點型數據,屬於浮點數據的一種。(K&R時期引入)
- double:雙精度浮點型數據,屬於浮點數據的一種。(K&R時期引入)
- _Bool:布爾型(C99標準新增)
- _Complex:複數的基本類型(C99標準新增)
- _Imaginary:虛數,與複數基本類型相似,沒有實部的純虛數(C99標準新增)
- _Generic:提供重載的介面入口(C11標準新增)
(2)類型修飾關鍵字
- short:修飾int,短整型數據,可省略被修飾的int。(K&R時期引入)
- long:修飾int,長整型數據,可省略被修飾的int。(K&R時期引入)
- long long:修飾int,超長整型數據,可省略被修飾的int。(C99標準新增)
- signed:修飾整型數據,有符號數據類型。(C89標準新增)
- unsigned:修飾整型數據,無符號數據類型。(K&R時期引入)
- restrict:用於限定和約束指針,並表明指針是訪問一個數據對象的唯一且初始的方式。(C99標準新增)
(3)複雜類型關鍵字
- struct:結構體聲明。(K&R時期引入)
- union:聯合體聲明。(K&R時期引入)
- enum:枚舉聲明。(C89標準新增)
- typedef:聲明類型別名。(K&R時期引入)
- sizeof:得到特定類型或特定類型變數的大小。(K&R時期引入)
- inline:內聯函數用於取代巨集定義,會在任何調用它的地方展開。(C99標準新增)
(4)存儲級別關鍵字
- auto:指定為自動變數,由編譯器自動分配及釋放。通常在棧上分配。與static相反。當變數未指定時預設為auto。(K&R時期引入)
- static:指定為靜態變數,分配在靜態變數區,修飾函數時,指定函數作用域為文件內部。(K&R時期引入)
- register:指定為寄存器變數,建議編譯器將變數存儲到寄存器中使用,也可以修飾函數形參,建議編譯器通過寄存器而不是堆棧傳遞參數。(K&R時期引入)
- extern:指定對應變數為外部變數,即標示變數或者函數的定義在別的文件中,提示編譯器遇到此變數和函數時在其他模塊中尋找其定義。(K&R時期引入)
- const:指定變數不可被當前線程改變(但有可能被系統或其他線程改變)。(C89標準新增)
- volatile:指定變數的值有可能會被系統或其他線程改變,強制編譯器每次從記憶體中取得該變數的值,阻止編譯器把該變數優化成寄存器變數。(C89標準新增)
(5)流程式控制制關鍵字
①跳轉結構
- 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時期引入)
(6)編譯
- define 預編譯巨集
- if 表達式 #else if 表達式 #else #endif 條件編譯
- ifdef 巨集 #else #endif 條件編譯
- ifndef 巨集 #else #endif 條件編譯與條件編譯
(一)順序結構
順序結構的程式設計是最簡單的,只要按照解決問題的順序寫出相應的語句就行,它的執行順序是自上而下,依次執行。
例如: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⑵;的執行順序是1->2->1...迴圈,2為迴圈條件。
④while
while迴圈結構,while(1) 2; 的執行順序是1->2->1...迴圈,1為迴圈條件
以上迴圈語句,當迴圈條件表達式為真則繼續迴圈,為假則跳出迴圈。
C語言的模塊化程式結構用函數來實現,即將複雜的C程式分為若幹模塊,每個模塊都編寫成一個C函數,然後通過主函數調用函數及函數調用函數來實現一大型問題的C程式編寫,因此常說:C程式=主函數+子函數。因此,對函數的定義、調用、值的返回等中要尤其註重理解和應用,並通過上機調試加以鞏固。
(一)判斷語句(選擇結構):
if 語句:“如果”語句;if—else 語句:“若…(則)…否則…”語句;switch 語句:“切換”語句;switch—case:“切換—情況”語句。
(二)迴圈語句(迴圈結構):
while 語句:“當…”語句;do—while 語句:“做…當…(時候)”語句;for 語句:條件語句(即“(做)…為了…”語句)。
(三)跳轉語句(迴圈結構:是否迴圈):
goto 語句:“轉舵”語句,也稱“跳轉”語句;break 語句:“中斷”(迴圈)語句,即結束整個迴圈;continue 語句:“繼續”語句(結束本次迴圈,繼續下一次迴圈);return 語句:“返回”語句。
需要說明的是:
1、一個C語言源程式可以由一個或多個源文件組成。[26]
2、每個源文件可由一個或多個函數組成。
3、一個源程式不論由多少個文件組成,都有一個且只能有一個main函數,即主函數。是整個程式的入口。
4、源程式中可以有預處理命令(包括include 命令,ifdef、ifndef命令、define命令),預處理命令通常應放在源文件或源程式的最前面。
5、每一個說明,每一個語句都必須以分號結尾。但預處理命令,函數頭和花括弧“}”之後不能加分號。(結構體、聯合體、枚舉型的聲明的“}”後要加“ ;”。)
6、標識符,關鍵字之間必須至少加一個空格以示間隔。若已有明顯的間隔符,也可不再加空格來間隔。
書寫規則
1、一個說明或一個語句占一行。
2、用{} 括起來的部分,通常表示了程式的某一層次結構。{}一般與該結構語句的第一個字母對齊,並單獨占一行。
3、低一層次的語句或說明可比高一層次的語句或說明縮進若幹格後書寫。以便看起來更加清晰,增加程式的可讀性。在編程時應力求遵循這些規則,以養成良好的編程風格。
C程式是由一組變數或是函數的外部對象組成的。 函數是一個自我包含的完成一定相關功能的執行代碼段。我們可以把函數看成一個“黑盒子”,你只要將數據送進去就能得到結果,而函數內部究竟是如何工作的的,外部程式是不知道的。外部程式所知道的僅限於輸入給函數什麼以及函數輸出什麼。函數提供了編製程式的手段,使之容易讀、寫、理解、排除錯誤、修改和維護。
C程式中函數的數目實際上是不限的,如果說有什麼限制的話,那就是,一個C程式中必須至少有一個函數,而且其中必須有一個並且僅有一個以main為名,這個函數稱為主函數,整個程式從這個主函數開始執行。
C 語言程式鼓勵和提倡人們把一個大問題劃分成一個個子問題,對應於解決一個子問題編製一個函數,因此,C 語言程式一般是由大量的小函數而不是由少量大函數構成的,即所謂“小函數構成大程式”。這樣的好處是讓各部分相互充分獨立,並且任務單一。因而這些充分獨立的小模塊也可以作為一種固定規格的小“構件”, 用來構成新的大程式。
C語言發展的那麼多年來,用C語言開發的系統和程式浩如煙海。在發展的同時也積累了很多能直接使用的庫函數。
ANSI C提供了標準C語言庫函數。
C語言初學者比較喜歡的Turbo C 2.0提供了400多個運行時函數,每個函數都完成特定的功能,用戶可隨意調用。這些函數總體分成輸入輸出函數、數學函數、字元串和記憶體函數、與BIOS和DOS有關的函數、 字元屏幕和圖形功能函數、過程式控制制函數、目錄函數等。
Windows系統所提供的Windows SDK中包含了數千個跟Windows應用程式開發相關的函數。
其他操作系統,如Linux,也同樣提供了大量的函數讓應用程式開發人員調用。
作為程式員應儘量熟悉目標平臺庫函數其功能。這樣才能游刃有餘地開發特定平臺的應用程式。比如作為Windows應用程式的開發者,應儘量熟悉Windows SDK;作為Linux應用程式開發者,應儘量熟悉Linux系統調用和POSIX函數規範。
比較特別的是,比特右移(>>)運算符可以是算術(左端補最高有效位)或是邏輯(左端補 0)位移。例如,將 11100011 右移 3 比特,算術右移後成為 11111100,邏輯右移則為 00011100。因算術比特右移較適於處理帶負號整數,所以幾乎所有的編譯器都是算術比特右移。
運算符的優先順序從高到低大致是:單目運算符、算術運算符、關係運算符、邏輯運算符、條件運算符、賦值運算符(=)和逗號運算符。