C 語言基本語法
本文內容來自網道專案,網道/WangDoc.com。
網道是一個文件網站,提供高質量的、擁有自主版權的、可以自由使用的中文軟體文件。鄙人無意間瀏覽到後發現網站提供的軟體文件內容講解十分通俗,並且質量較高,特此收藏與分享。
本文乃至本系列都是謄抄於網道C語言教程,如有各種不當之處,還請速速聯絡。
1. 語句
C 語言的程式碼由一行行語句(statement)組成。語句就是程式執行的一個操作命令。C 語言規定,語句必須使用分號結尾,除非有明確規定可以不寫分號。
int x = 1;
上面就是一個變數宣告語句,宣告整數變數x
,並且將值設為1
。
多個語句可以寫在一行。
int x; x = 1;
上面示例是兩個語句寫在一行。所以,語句之間的換行符並不是必需的,只是為了方便閱讀程式碼。
一個語句也可以寫成多行,這時就要依靠分號判斷語句在哪一行結束。
int x;
x
=
1
;
上面示例中,第二個語句x = 1;
被拆成了四行。編譯器會自動忽略程式碼裡面的換行。單個分號也是有效語句,稱為“空語句”,雖然毫無作用。
;
2. 表示式
C 語言的各種計算,主要通過表示式完成。表示式(expression)是一個計算式,用來獲取值。
1 + 2
上面程式碼就是一個表示式,用來獲取1 + 2
這個算術計算的結果。
表示式加上分號,也可以成為語句,但是沒有實際的作用。
8;
3 + 4;
上面示例是兩個表示式,加上分號以後成為語句。
表示式與語句的區別主要是兩點:
- 語句可以包含表示式,但是表示式本身不構成語句。
- 表示式都有返回值,語句不一定有。因為語句用來執行某個命令,很多時候不需要返回值,比如變數宣告語句(
int x = 1
)就沒有返回值。
3. 語句塊
C 語言允許多個語句使用一對大括號{}
,組成一個塊,也稱為複合語句(compounded statement)。在語法上,語句塊可以視為多個語句組成的一個複合語句。
{
int x;
x = 1;
}
上面示例中,大括號形成了一個語句塊。
大括號的結尾不需要新增分號。
4. 空格
C 語言裡面的空格,主要用來幫助編譯器區分語法單位。如果語法單位不用空格就能區分,空格就不是必須的,只是為了增加程式碼的可讀性。
int x = 1;
// 等同於
int x=1;
上面示例中,賦值號(=
)前後有沒有空格都可以,因為編譯器這裡不借助空格,就能區分語法單位。
語法單位之間的多個空格,等同於單個空格。
int x = 1;
上面示例中,各個語法單位之間的多個空格,跟單個空格的效果是一樣的。
空格還用來表示縮排。多層級的程式碼有沒有縮排,其實對於編譯器來說並沒有差別,沒有縮排的程式碼也是完全可以執行的。強調程式碼縮排,只是為了增強程式碼可讀性,便於區分程式碼塊。
大多數 C 語言的風格要求是,下一級程式碼比上一級縮排4個空格。為了書寫的緊湊,本書採用縮寫兩個空格。
// 縮排四個空格
if(x > 0)
printf("positive\n");
// 縮排兩個空格
if(x > 0)
printf("positive\n");
只包含空格的行被稱為空白行,編譯器會完全忽略該行。
5. 註釋
註釋是對程式碼的說明,編譯器會自動忽略註釋,也就是說,註釋對實際程式碼沒有影響。
C 語言的註釋有兩種表示方法。第一種方法是將註釋放在/*...*/
之間,內部可以分行
/* 註釋 */
/*
這是一行註釋
*/
這種註釋可以插在行內。
int open(char* s/* file name */, int mode);
上面示例中,/* filename */
用來對函式引數進行說明,跟在它後面的程式碼依然會有效執行。
這種註釋一定不能忘記寫結束符號*/
,否則很容易導致錯誤。
printf("a "); /* 註釋一
printf("b ");
printf("c "); /* 註釋二 */
printf("d ");
上面示例的原意是,第一行和第三行程式碼的尾部,有兩個註釋。但是,第一行註釋忘記寫結束符號,導致註釋一延續到第三行結束。
第二種寫法是將註釋放在//
後面,從雙斜槓到行尾都屬於註釋。這種註釋只能是單行,可以放在行首,也可以放在一行語句的結尾。這是C99 標準新增的語法。
// 這是一行註釋
int x = 1; // 這也是註釋
不管哪一種註釋,都不能放在雙引號裡面。雙引號裡面的註釋符號,會成為字串的一部分,解釋為普通符號,失去註釋作用。
printf("// hello /* world */ ");
上面示例中,雙引號裡面的註釋符號,都會被視為普通字元,沒有註釋作用。
編譯時,註釋會被替換成一個空格,所以min/* space */Value
會變成min Value
,而不是minValue
。
6. printf()
6.1 基本語法
本書的示例會大量用到printf()
函式,這裡先介紹一下這個函式。
printf()
的作用是將引數文字輸出到螢幕。它名字裡面的f
代表format
(格式化),表示可以定製輸出文字的格式。
printf("Hello World");
上面命令會在螢幕上輸出一行文字"Hello World"。
printf()
不會在行尾自動新增換行符,執行結束後,游標就停留在輸出結束的地方,不會自動換行。為了讓游標移到下一行的開頭,可以在輸出文字的結尾,新增一個換行符\n
。
printf("Hello World\n");
如果文字內部有換行,也是通過插入換行符來實現。
printf("Hello\nWorld\n");
上面示例先輸出一個Hello
,然後換行,在下一行開頭輸出World
,然後又是一個換行。
上面示例也可以寫成兩個printf()
,效果完全一樣。
printf("Hello\n");
printf("World\n");
printf()
是在標準庫的標頭檔案stdio.h
定義的。使用這個函式之前,必須在原始碼檔案頭部引入這個標頭檔案。
#include <stdio.h>
int main()
{
printf("Hello World\n");
}
上面示例中,只有在原始碼頭部加上#include <stdio.h>
,才能使用printf()
這個函式。
#include
指令的詳細解釋,請看《前處理器》一章。
6.2 佔位符
printf()
可以在輸出文字中指定佔位符。所謂"佔位符",就是在這個位置可以用其他值代入。
// 輸出 There are 3 apples
printf("There are %i apples\n", 3);
上面示例中,There are %i apples\n
是輸出文字,裡面的%i
就是佔位符,表示這個位置要用其它值來替換。佔位符的第一個字元一律為百分號%
,第二個字元表示佔位符的型別,%i
表示這裡代入的值必須是一個整數。
printf()
的第二個引數就是替換佔位符的值,上面的例子是整數3
替換%i
。執行後的輸出結果就是There are 3 apples
。
常用的佔位符除了%i
,還有%s
表示代入的是字串。
printf("%s will come tonight\n", "Jane");
上面示例中,%s
表示代入的是一個字串,所以printf()
的第二個引數就必須是字串,這個例子是Jane
。執行後的輸出就是Jane will come tonight
。
輸出文本里面可以使用多個佔位符。
printf("%s says it is %i o'clock\n", "Ben", 21);
上面示例中,輸出文字%s says it is %i o'clock
有兩個佔位符,第一個是字串佔位符%s
,第二個是整數佔位符%i
,分別對應printf()
的第二個引數(Ben
)和第三個引數(21
)。執行後的輸出就是Ben says it is 21 o'clock
。
printf()
引數與佔位符是一一對應關係,如果有n
個佔位符,printf()
的引數就應該有n + 1
個。如果引數個數少於對應的佔位符,printf()
可能會輸出記憶體中的任意值。
printf()
的佔位符有許多種類,與 C 語言的資料型別相對應。下面按照字母順序,列出常用的佔位符,方便查詢,具體含義在後面章節介紹。
%a
:浮點數。%A
:浮點數。%c
:字元。%d
:十進位制整數。%e
:使用科學計數法的浮點數,指數部分的e
為小寫。%E
:是用科學計數法的浮點數,指數部分的E
為大寫。%i
:整數,基本等同於%d
。%f
:小數(包含float
型別和double
型別)。%g
:6個有效數字的浮點數,整數部分一旦超過6位,就會自動轉為科學計數法,指數部分的e
為小寫。%G
:等同於%g
,唯一的區別是指數部分的E
為大寫。%hd
:十進位制 short int 型別。%ho
:八進位制 short int 型別。%hx
:十六進位制 short int 型別。%hu
:unsigned short int 型別。%ld
:十進位制 long int 型別。%lo
:八進位制 long int 型別。%lx
:十六進位制 long int 型別。%lu
:unsigned long int 型別。%lld
:十進位制 long long int 型別。%llo
:八進位制 long long int 型別。%llx
:十六進位制 long long int 型別。%llu
:unsigned long long int 型別。%Le
:科學計數法表示的 long double 型別浮點數。%Lf
:long double 型別浮點數。%n
:已輸出的字串數量。該佔位符本身不輸出,只將值儲存在指定變數之中。%o
:八進位制整數。%p
:指標。指標就是地址。%s
:字串。%u
:無符號整數(unsigned int)。%x
:十六進位制整數。%zd
:size_t
型別。%%
:輸出一個百分號。
6.3 輸出格式
printf()
可以定製佔位符的輸出格式。
(1)限定寬度
printf()
允許限定佔位符的最小寬度。
printf("%5d\n", 123); // 輸出為 " 123"
上面示例中,%5d
表示這個佔位符的寬度至少為5位。如果不滿5位,對應的值的前面會新增空格。
輸出的值預設是右對齊,即輸出內容前面會有空格;如果希望改成左對齊,在輸出內容後面新增空格,可以在佔位符的%
的後面插入一個-
號。
printf("%d-5d\n", 123); // 輸出為 "123 "
上面示例中,輸出內容123
的後面添加了空格。
對於小數,這個限定符會限制所有數字的最小顯示寬度。
// 輸出 " 123.450000"
printf("%12f\n", 123.45);
上面示例中,%12f
表示輸出的浮點數最少要佔據12位。由於小數的預設顯示精度是小數點後6位,所以123.45
輸出結果的頭部會新增2個空格。
(2)總是顯示正負號
預設情況下,printf()
不對正數顯示+
號,只對負數顯示-
號。如果想讓正數也輸出+
號,可以在佔位符的%
後面加一個+
。
printf("%+d\n", 12); // 輸出 +12
printf("%+d\n", -12); // 輸出 -12
上面示例中,%+d
可以確保輸出的數值,總是帶有正負號。
(3)限定小數位數
輸出小數時,有時希望限定小數的位數。舉例來說,希望小數點後面只保留兩位,佔位符可以寫成%.2f
。
// 輸出 Number is 0.50
printf("Number is %.2f\n", 0.5);
上面示例中,如果希望小數點後面輸出3位(0.500
),佔位符就要寫成%.3f
。
這種寫法可以與限定寬度佔位符,結合複用。
// 輸出為 " 0.50"
printf("%6.2f\n", 0.5);
上面示例中,%6.2f
表示輸出字串最小寬度為6,小數位數為2.所以,輸出字串的頭部有兩個空格。
最小寬度和小數位數這兩個限定值,都可以用*
代替,通過printf()
的引數傳入。
printf("%*.*f\n", 6, 2, 0.5);
// 等同於
printf("%6.2f\n", 0.5);
上面示例中,%*.*f
的兩個星號通過printf()
的兩個引數6
和2
傳入。
(4)輸出部分字串
%s
佔位符用來輸出字串,預設是全部輸出。如果只想輸出開頭的部分,可以用%.[m]s
指定輸出的長度,其中[m]
代表一個數字,表示所要輸出的長度。
// 輸出 hello
printf("%.5s\n", "hello world");
上面示例中,佔位符%.5s
表示只輸出字串"hello world"的前5個字元,即"hello"。
7. 標準庫,標頭檔案
程式需要用到的功能,不一定需要自己編寫, C 語言可能已經自帶了。程式設計師只要去呼叫這些自帶的功能,就省得自己編寫程式碼了。舉例來說,printf()
這個函式就是 C 語言自帶的,只要去呼叫它,就能實現在螢幕上輸出內容。
C 語言自帶的所有這些功能,統稱為"標準庫"(standard library),因為它們是寫入標準的,到底包括哪些功能,應該怎麼使用的,都是規定好的,這樣才能保證程式碼的規範和可移植。
不同的功能定義在不同的檔案裡面,這些檔案統稱為"標頭檔案"(header file)。如果系統自帶某一個功能,就一定還會自帶描述這個功能的標頭檔案,比如printf()
的標頭檔案就是系統自帶的stdio.h
。標頭檔案的字尾通常是.h
。
如果要使用某個功能,就必須先載入對應的標頭檔案,載入使用的是#include
命令。這就是為什麼使用printf()
之前,必須先載入stdio.h
的原因。
#include <stdio.h>
注意,載入標頭檔案的#include
語句不需要分號結尾,詳見《前處理器》一章。
本系列內容來自網道專案,網道/WangDoc.com。