【C語言入門】C語言的組成結構(基礎完整篇)!

2021-02-13 C語言編程俱樂部

C是一種具有模塊化設計的命令式程式語言,具有簡約、直觀的設計風格,與相對清晰、簡單的語言結構。

在談C的語言結構之前,需要先解釋一些基本元素的含義。

一、表達式

表達式是一個或多個變量、常量、函數與運算符按照特定規則的組合,表達式根據特定的優先級與運算符進行計算並返回一個值。

注意:單個變量、常量或函數名也是一個表達式。

以下面表達式為例:

var = fn(1) + 5

其中var、fn、1、5都是表達式,其返回值為自身的值;fn(1)也是一個表達式,返回函數調用的返回值;fn(1) + 5也是一個表達式,返回算術運算的結果;var = fn(1) + 5也是一個表達式,返回賦值號左邊的值,此例中此值被丟棄。

特別地,調用返回值為void類型的函數將返回一個void類型的值,但此值無法被使用,只能丟棄。

1、完整表達式

如果一個表達式不是其他表達式的子表達式,則稱這個表達式為「完整表達式」。

以下面幾個語句為例:

var = 1 + 2;

fn(var + 1);

if (var + 1) ;

    ✪ 表達式語句中的整個表達式為完整表達式,如上面的var = 1 + 2和fn(var + 1),但第二行的var + 1不屬於完整表達式。(函數調用實際上是運算符()對函數指針和參數進行運算)

    ✪ if、while、switch括號中的表達式以及for括號中的每個分量都是完整表達式,所以第三行的var + 1是完整表達式。

二、副作用

除了返回值以外對程序造成的其他影響稱為副作用。比如修改變量的值,執行I/O操作等。

對於如下表達式:

var = 5

表達式的返回值為5,副作用為將5賦值給變量var。

而對於以下表達式:

1 + 2

表達式返回3,沒有副作用。

通常說起「副作用」,總是覺得無關緊要或儘量避免,但對於命令式程式語言來說,副作用才是程序執行的主要目的。

比如我們調用printf函數,我們通常並不關心它的返回值,而是需要它把特定的字符輸出到屏幕,而標準輸出正是這個函數的副作用。

三、語句

語句是C的基本執行單元,語句不返回結果,僅執行副作用。語句可分為簡單語句和複合語句。

在C語言中,「;」 不是分隔符(for語句中的 「;」 除外),而是大部分語句的結尾。

申明不屬於語句,因為申明通常不產生副作用,即使有時候會產生副作用(如初始化),但仍不將其視為語句,申明也以「;」結尾。

C有5種語句:

    ✪ 表達式語句

    ✪ 跳轉語句

    ✪ 選擇語句

    ✪ 循環語句

    ✪ 標籤語句

1、簡單語句和複合語句

簡單語句指內部不包含其他語句的語句。如表達式語句和跳轉語句。最簡單的語句是只有一個 「;」 的空語句。

複合語句的定義與簡單語句相反,即其內部有其他語句。

將幾個語句用 {} 括起來就形成了複合語句「塊」,最簡單的複合語句是空塊 {}。

複合語句可以進行多次複合,比如塊可以嵌套,複合語句的子語句可以是其他複合語句。

C語言沒有else if關鍵字,這種語法結構只是將上一個if語句的else部分複合了另一個if語句,將他們寫在一起是為了使代碼更簡潔。

2、表達式語句

表達式語句為一個完整表達式後跟一個分號構成的語句。若表達式為空,就構成了空語句。

表達式語句是最簡單也是最常見的語句。以下語句都是表達式語句:

;

1 + 2;

var = 5;

printf("hello, world\n");

3、跳轉語句

跳轉語句用於改變代碼的執行順序。跳轉語句包括continue、break、return、goto語句。

4、選擇語句

選擇語句是複合語句,其作用是根據特定表達式的值對程序執行進行跳轉。如if、if else、switch語句。

5、循環語句

循環語句是複合語句,其作用是根據特定表達式的值讓一部分代碼反覆執行多次,如while、dowhile、for語句。循環語句也可以通過選擇語句和跳轉語句實現。

6、標籤語句

在其他語句前加上標籤即是標籤語句。標籤語句是複合語句,可以在任何語句(包括標籤語句)前添加標籤。

因為申明不是語句,所以不能在申明前添加標籤。對於下面的代碼,gcc給出如下錯誤提示:

lable:

    int var = 0;

error: a label can only be part of a statement and a declaration is not a statement

case 標籤是一種特殊的標籤,其標誌是在標籤前的case關鍵字。case標籤只能在switch語句中使用,case標籤允許且只允許標籤名使用整數,並且把標籤的作用域限定在當前的switch語句中。

標籤是語句的一部分,而不只是個記號,所以塊末尾不能是標籤。

比如下面語句:

switch (var) {

case 1:

case 2:

case 3:

    ;

}

最後的分號是不可以省略的,空語句複合case 3標籤形成標籤語句,然後又複合case 1和case 2,所以這個塊內只有一條完整的複合語句。

四、C語言結構

C語言代碼文件包括源文件和頭文件,源文件可以進行編譯和連結,頭文件一般通過預處理指令包含到源文件中使用。

源文件由預處理指令、申明、類型定義、函數定義和注釋組成。

預處理指令和注釋可以出現在源文件的任何位置而不影響其功能,而申明和類型定義的位置決定了其作用域。

申明有時會伴隨定義,定義一定會包含申明。

函數定義由返回值類型、函數名、參數列表和語句塊組成。語句只能出現在函數定義內部。

C源文件必須有且只能有一個main函數,C89規定,main函數的返回值必須為int類型,如果程序正常終止,應返回0。

標準的main函數應寫為 int main(void); 或 int main(int argc, char const *argv[]); 。

五、序列點

C語言通過序列點控制副作用的執行。在該點處之前的求值的所有的副作用已經發生,在它之後的求值的所有副作用仍未開始。

序列點的存在一定程度上保證了程序按照預期執行,但仍存在一些未定義的行為。

C中的序列點很少,因為C追求效率,更少的序列點可以給編譯器更多優化的空間。

注意:C中有很多符號同時承擔多種功能,在不同語境下扮演不同的身份。

C的序列點包括:

1、&& 與 || 運算符

&& 與 || 運算符會先對左邊的表達式求值並執行副作用。

對 && 運算符來說,只有當左邊表達式的值為1時才對右邊的表達式求值並執行副作用。

這是對程序的一種優化,因為根據「與」邏輯,如果左邊表達式的值為0,則總表達式的值定為0,無需對右邊表達式進行計算。根據這一特性,可以寫出更加符合人類邏輯的代碼。

if (var != 0 && 3 == 100 / var) {}

如果沒有此序列點,則可能會出現0做除數的錯誤。

|| 運算符同理,只有當左邊表達式的值為0時才對右邊的表達式求值並執行副作用。

2、逗號運算符

「,」 在C語言中有很多用途,在某些地方它是分隔符,在某些地方它是運算符。比如以下表達式:

var = 1, var = 2

這裡的 「,」 不是分隔符,而是運算符。此逗號運算符的兩邊是兩個賦值表達式,逗號表達式先對左邊的表達式求值並執行副作用,此時var的值被修改為1,之後對右邊的表達式求值並執行副作用,var的值被修改為2,最後,逗號表達式返回右邊表達式的值,即2。

逗號表達式的特性可以使兩個表達式像兩個表達式語句那樣執行,適合用在需要用表達式代替語句塊的地方,如 for 語句的括號內。

3、三元運算符 ? : 中的 ?

在 ? 前的表達式求值並執行副作用後,才判斷返回其後哪個表達式的值。並且,如果確定返回某個表達式的值,則不會對另一個表達式求值或執行副作用。

? : 表達式的這個特性使其行為與if else表現一致。

4、完整表達式的末尾

完整表達式的末尾也是一個序列點,這保證了表達式語句的副作用按照其書寫順序執行。

同時,根據前面對完整表達式的定義,if、while、switch括號中的表達式以及for括號中的每個分量都是完整表達式,這些表達式的副作用也都會在語句其他部分開始前執行。

5、函數調用與返回

函數調用時參數列表中的逗號不是表達式,而是分隔符。

參數列表的求值順序是未定義的,比如 fn(a++, b--),a++和b--的求值順序是未知的,取決於編譯器。

此處的序列點表現為在進入函數前,所有表達式的副作用都已經完成;函數返回時,返回值已經拷貝到調用處。

6、初始化末尾

因為初始化是申明的一部分,不屬於語句或表達式,所以不能套用表達式的說法,但其表現是類似的。

如下申明:

int var = 5;

在分號前已經完成副作用,即把var初始化為5。

7、初始化列表中的逗號分隔符

初始化列表中的逗號是分隔符而不是運算符。

初始化列表中的表達式按照從左到右的順序求值並執行副作用。

如下代碼:

int var = 0;

int array[] = { var++, var++, var++ };

8、申明中的逗號分隔符

申明中的逗號是分隔符而不是運算符。

如下代碼:

int a = 0;

int b = a++, c = a++;

b、c分別被初始化為0、1。

而且,在逗號前的變量已經申明完成,逗號後的則不然。

如下代碼:

int a = 0, b = a; //Correct

int c = d, d = 0;  //Error

在申明b前,a已經申明並初始化完成,所以可以用a初始化b。而在申明c時還沒有申明d,所以初始化會報錯。

因為缺少序列點,C會產生很多未定義的行為。最典型的例子是:

int var = 0;

var = var++;

根據優先級,表達式var = var++的值是確定的,然而賦值和自增副作用的執行順序是未定義的,所以var的值是未知的。如果用gcc編譯這段代碼,var的值為0,比較符合預期;但在VC++中,var的值為1。

所以我們應避免在表達式中同時使用某一變量和它的自增表達式。


最後,不管你是轉行也好,初學也罷,進階也可,如果你想學編程~

【值得關注】我的C/C++編程學習交流俱樂部:

【Q群:795246887】

問題答疑,學習交流,技術探討,還有超多編程資源大全,零基礎的視頻也超棒~

點擊下方 ↓ 原文連結即可直接進入~~~

相關焦點

  • c語言入門教程
    1.c語言入門教程--簡介  C語言是一種電腦程式設計語言,它既具有高級語言的特點,又具有彙編語言的特點。
  • C語言入門 — 一篇最全的C語言基礎知識.
    c語言入門C語言一經出現就以其功能豐富、表達能力強、靈活方便、應用面廣等特點迅速在全世界普及和推廣。
  • C語言入門筆記(一)
    c語言入門C語言一經出現就以其功能豐富、表達能力強、靈活方便、應用面廣等特點迅速在全世界普及和推廣。
  • C語言從入門到放棄(3)
    程序的幾種基本結構程序設計模式    C語言中,常用的流程控制結構分為順序結構、選擇結構和循環結構。由這三種結構可組成各種複雜的程序。順序結構是三種結構中最簡單,最常見的程序結構。三種流程控制結構,使用特定的流程控制語句,從而實現程序的各種結構方式。
  • 學習C語言必看的最經典書籍
    來源:互動出版網學習c語言必看的最經典書籍推薦一:《新概念51單片機C語言教程--入門
  • c語言50本電子書
    495個C語言問題.pdfC Primer Plus 第6版 中文版 高清完整PDF版.pdf
  • C 語言基礎
    C 語言基礎// 引入頭文件。裡面包含了重要的 printf。#include <stdio.h>// 入口函數。// 參數一指輸入的參數個數,參數二保存了所有參數。// 返回值為 int 類型,一般 0 代表成功,負數代表失敗。
  • C語言程序設計視頻教程C++
    計算機作業系統/組成原理/數據結構視頻教程 自學考研課程 嚴蔚敏大學計算機專業視頻教程173門C語言JAVE網絡電腦自學零基礎課程計算機專業視頻課程計算機原理人工智慧導論/軟體工程/java/c++等20AP微積分物理心理統計化學生物歷史計算機微觀經濟網課課程視頻AI人工智慧視頻教程python深度學習計算機視覺機器人工程師課程
  • C 語言基礎,來嘍!
    、面向過程的語言,C 語言廣泛應用於底層開發,C 語言在計算機體系中佔據著不可替代的作用,可以說 C 語言是編程的基礎,也就是說,不管你學習任何語言,都應該把 C 語言放在首先要學的位置上。計算機科學理論:簡稱 CS、是系統性研究信息與計算的理論基礎以及它們在計算機系統中如何實現與應用的實用技術的學科。
  • 【C語言系列】基礎語法案例分析(初級篇)
    下面這些C語言基礎算法案例都是經過測試和驗證過了的,歡迎各位使用。
  • 19本C語言學習書籍
    入門篇1、《C語言程序設計》本書是C語言之父和著名科學家Brian W. Kernighan 合著的一本介紹C語言的權威經典著作。我們現在見到的大量論述C語言程序設計的教材和專著均以此書為藍本。人們熟知的「hello,World"程序就是由本書首次引入的,現在,這一程序已經成為眾多程序設計語言入門的第一課。
  • c語言基礎知識入門(四)
    #include <stdio.h>//聲明文件 .h .hpp//<> 表示尋找系統的資源//"" 表示尋找開發者定義的聲明文件//.c .cpp 實現文件//代碼結構//main 函數只能存在一個int mainT1() {
  • C語言入門教程(一)
    C語言入門教程(一):輸入輸出函數、程序中的數據實驗環境Ubuntu 16.04 終端gcc
  • C語言最全入門筆記
    c語言入門C語言一經出現就以其功能豐富、表達能力強、靈活方便、應用面廣等特點迅速在全世界普及和推廣。
  • C語言入門筆記,一級棒
    :,其格式為:表達式1 ? 表達式2 : 表達式3;執行過程是:先判斷表達式1的值是否為真,如果是真的話執行表達式2;如果是假的話執行表達式3。簡單if語句的基本結構如下:if(表達式){執行代碼塊;}其語義是:如果表達式的值為真,則執行其後的語句,否則不執行該語句。注意:if()後面沒有分號,直接寫{}分支結構之簡單if-else語句簡單的if-else語句的基本結構:
  • 最全C語言入門筆記
    來自公眾號:築夢編程c語言入門C語言一經出現就以其功能豐富、表達能力強、靈活方便、應用面廣等特點迅速在全世界普及和推廣。
  • C語言入門學習和書籍推薦
    1、C語言適合當第一門程式語言學習①、C語言語法相對簡單,但又比較完整和嚴謹,包含該有的各種元素。學完C語言語法,要學習其它程式語言就很容易了。②、C語言接近底層,可以了解內存和計算機的基本原理。③、許多基礎課程比如算法與數據結構教材都是以C語言為例子的,特別是中國版的書籍。
  • C語言快速入門系列(三)
    本節引言:在上一節中,對C語言的基本語法進行了學習,類比成學英語的話,我們現在只是會單詞而已,組成一個個句子還需要學習一些語法
  • C語言編譯器有哪些?C語言編譯軟體下載
  • 入門必備—常用的C語言編程軟體
    C語言是每一個計算機專業的學生最先接觸也是最為基礎的程式語言,學習C語言有助於更好的理解C++,Java,C#以及其他基於C的特性的語言