- C語(yǔ)言從入門到精通(第2版)
- 龍馬高新教育策劃 國(guó)家863中部軟件孵化器編著
- 107字
- 2019-01-02 04:49:37
第2章 C程序的組成
本章視頻教學(xué)錄像:1 小時(shí)28 分鐘
在C語(yǔ)言中,根據(jù)存儲(chǔ)方式和表示形式,數(shù)據(jù)有常量和變量之分,就像方程有已知數(shù)和未知數(shù)一樣。
本章要點(diǎn)(已掌握的在方框中打鉤)
□ 聲明區(qū)
□ 主函數(shù)
□ 函數(shù)定義區(qū)
□ 注釋
□ 代碼的規(guī)矩
2.1 簡(jiǎn)單例子
本節(jié)視頻教學(xué)錄像:7分鐘
【范例2-1】 計(jì)算圓的周長(zhǎng)。
⑴ 在Visual C++ 6.0中,新建名為“計(jì)算圓周長(zhǎng).c”的【Text File】文件。
⑵ 在代碼編輯區(qū)域輸入以下代碼(代碼2-1.txt)。
01 /*內(nèi)容:計(jì)算圓周長(zhǎng) 02 目的:了解C語(yǔ)法*/ 03 #include<stdio.h> /*包含標(biāo)準(zhǔn)輸入輸出頭文件*/ 04 #include<math.h> /*包含數(shù)學(xué)函數(shù)庫(kù)頭文件*/ 05 #define PI 3.14 /*定義常量PI,它的值是3.14*/ 06 int main() /*主函數(shù)*/ 07 { 08 int radius; /*整型變量,存儲(chǔ)半徑值*/ 09 float circum; /*浮點(diǎn)型變量,存儲(chǔ)周長(zhǎng)值*/ 10 radius=2; /*半徑賦值*/ 11 circum=2*PI*radius; /*計(jì)算周長(zhǎng)*/ 12 printf("變量radius地址是%d\n",&radius); /*輸出變量radius存儲(chǔ)地址*/ 13 printf("半徑開方值是%f\n",sqrt(radius)); /*輸出變量radius的開方值*/ 14 printf("半徑是%d,周長(zhǎng)是%f\n",radius,circum); /*輸出變量radius值和circum值*/ 15 return 0; /*返回值*/ 16 } /*函數(shù)體結(jié)束*/
【運(yùn)行結(jié)果】
編譯、連接、運(yùn)行程序,即可在命令行中輸出以下結(jié)果。

【范例分析】
這個(gè)范例的目的是讓大家看到一個(gè)較復(fù)雜的C程序的組成,所謂復(fù)雜只是多了些說明和代碼。
2.2 聲明區(qū)
本節(jié)視頻教學(xué)錄像:23分鐘
2.2.1 頭文件
一個(gè)C程序可以由若干個(gè)源程序文件組成,每一個(gè)源文件可以由若干個(gè)函數(shù)和預(yù)處理命令以及全局變量聲明部分組成,每一個(gè)函數(shù)由函數(shù)首部和函數(shù)體組成。C程序的結(jié)構(gòu)如圖所示。

作為一名程序開發(fā)人員,不可能每次編寫都從最底層開發(fā)。比如在上例中,要輸入一串字符到輸出設(shè)備上,我們需要做的僅是調(diào)用printf()函數(shù),至于“Hello C!”是怎樣顯示的,我們并不關(guān)心。我們認(rèn)識(shí)printf()函數(shù),在編寫程序時(shí)調(diào)用它,更需要讓程序認(rèn)識(shí)它,這樣才能使用printf()函數(shù)提供的功能,這就需要使用#include <stdio.h>,包含標(biāo)準(zhǔn)輸入輸出頭文件,這樣程序就能夠認(rèn)識(shí)printf()函數(shù),并執(zhí)行其功能。
C提供有豐富的函數(shù)集,我們稱之為標(biāo)準(zhǔn)函數(shù)庫(kù)。標(biāo)準(zhǔn)函數(shù)庫(kù)包括15個(gè)頭文件,借助這些函數(shù)可以完成不同的功能。
例如,【范例2-1】中有#include<math.h>時(shí),就可以使用該數(shù)學(xué)函數(shù)庫(kù)頭文件提供的如開平方函數(shù)sqrt(),求出半徑radius為2時(shí)的開平方值1.414;又如,當(dāng)程序包含頭文件“malloc.h”時(shí),就可以完成對(duì)內(nèi)存申請(qǐng)和釋放等功能。
2.2.2 函數(shù)聲明
標(biāo)準(zhǔn)C語(yǔ)言引入了新的更好的函數(shù)聲明方法,即用函數(shù)原型指定函數(shù)更多的信息,通過函數(shù)原型可以將函數(shù)的名字和函數(shù)類型以及形式參數(shù)的個(gè)數(shù)、類型、順序通知編譯系統(tǒng),以便在調(diào)用函數(shù)時(shí),系統(tǒng)可以對(duì)照檢查。
函數(shù)聲明由函數(shù)返回類型、函數(shù)名和形參列表組成。形參列表必須包括形參類型,但是不必對(duì)形參命名。這3個(gè)元素被稱為函數(shù)原型,函數(shù)原型描述了函數(shù)的接口。定義函數(shù)的程序員提供函數(shù)原型,使用函數(shù)的程序員就只需要對(duì)函數(shù)原型編輯即可。
函數(shù)聲明的一般形式為:
函數(shù)返回類型 函數(shù)名(參數(shù)類型1,參數(shù)類型2,……);
函數(shù)聲明包括函數(shù)的返回類型和函數(shù)名,來看下面這個(gè)例子。
01 int fun(int a,int b); 02 void display(); 03 float fn(float x);
其中,int、void和float都是函數(shù)返回類型,也屬于數(shù)據(jù)類型。fun、display和fn是所調(diào)用的函數(shù)名。也就是說,fun()函數(shù)返回的數(shù)據(jù)類型為整型int;display()函數(shù)返回的類型為void型,指函數(shù)無(wú)返回值;fn()返回的數(shù)據(jù)類型為浮點(diǎn)型float。
fun(int a, int b)函數(shù)內(nèi)部的a和b為形參,其參數(shù)類型都為int型。fn (float x)函數(shù)內(nèi)部參數(shù)x的類型為float型。函數(shù)聲明中的形參名往往被忽略,如果聲明中提供了形參的名字,也只是用作輔助文檔。另外要注意函數(shù)聲明是一個(gè)語(yǔ)句,后面不可漏分號(hào)!
進(jìn)一步對(duì)函數(shù)做解釋,需要注意的有以下幾點(diǎn)。
⑴ 函數(shù)名稱后面必須有小括號(hào),不能省略,這是函數(shù)的特征。
⑵ 函數(shù)結(jié)束必須有分號(hào),不能省略。
⑶ 字符串結(jié)尾有這樣的內(nèi)容“\n”,它叫做轉(zhuǎn)義符,表示的含義是把光標(biāo)移動(dòng)到下一行的行首,也就是回車換行,因?yàn)槲覀儫o(wú)法直接通過鍵盤輸入換行的指令,所以需要使用轉(zhuǎn)義符;又比如輸出內(nèi)容后希望返回該行的行首,重新輸出內(nèi)容,鍵盤上也沒有對(duì)應(yīng)的功能鍵,我們就可以使用回車符轉(zhuǎn)義符“\r”來代替。當(dāng)然,轉(zhuǎn)義還包含其他內(nèi)容,后續(xù)章節(jié)中會(huì)詳細(xì)講述。
2.2.3 變量聲明
在大多數(shù)語(yǔ)言中,在使用一個(gè)變量之前,都要對(duì)這個(gè)變量進(jìn)行聲明,C語(yǔ)言同樣如此。那么,什么是變量的聲明呢?有什么作用呢?變量的聲明其實(shí)就是在程序運(yùn)行前,告訴編譯器程序使用的變量以及與這些變量相關(guān)的屬性,包括變量的名稱、類型和長(zhǎng)度等。這樣,在程序運(yùn)行前,編譯器就可以知道怎樣給變量分配內(nèi)存空間,可以優(yōu)化程序。
變量的聲明語(yǔ)句的形式如下:
變量類型名 變量名
變量的聲明包括變量類型名和變量名兩個(gè)部分。來看下面的例子:
01 int num 02 double area 03 char ppt
其中,int、double和char是變量類型名,num、area和ppt是變量名。其實(shí),變量類型名也是數(shù)據(jù)類型的一種,就是說變量num是int類型,area是double類型,ppt是char類型。
變量類型名是C語(yǔ)言自帶的數(shù)據(jù)類型和用戶自定義的數(shù)據(jù)類型。C語(yǔ)言自帶的數(shù)據(jù)類型包括整型、字符型、浮點(diǎn)型、枚舉型和指針類型等。
變量名其實(shí)就是一個(gè)標(biāo)識(shí)符,當(dāng)然,標(biāo)識(shí)符的命名規(guī)則在此處同樣適用。除此之外,變量命名的時(shí)候還需要注意以下幾點(diǎn)。
⑴ 變量名區(qū)分大小寫,變量Num和num是兩個(gè)不同的變量。
⑵ 變量的命名最好與實(shí)際應(yīng)用有關(guān)聯(lián),例如:num一般表示數(shù)量,area表示面積等。
⑶ 變量的命名必須在變量使用之前。
提示
如果變量沒有經(jīng)過聲明而直接使用,則會(huì)出現(xiàn)編譯器報(bào)錯(cuò)的現(xiàn)象。
下面用一個(gè)例子來驗(yàn)證聲明必須在變量使用的前面。
【范例2-2】 驗(yàn)證未聲明的標(biāo)識(shí)符不可用。
⑴ 在Visual C++ 6.0中,新建名為“undeclaredvar.c”的【Text File】文件。
⑵ 在編輯窗口中輸入以下代碼(代碼2-2.txt)。
01 #include<stdio.h> 02 int main(void) 03 { 04 printf("output undeclaredvar num=%d\n",num); 05 return 0; 06 }
【運(yùn)行結(jié)果】
編譯后顯示出錯(cuò),信息如下:
undeclaredvar.c(4) : error C2065: 'num' : undeclared identifier
【范例分析】
在此例子中,沒有對(duì)標(biāo)識(shí)符num進(jìn)行聲明就直接引用,編譯器不知道num是什么,所以調(diào)試時(shí)編譯器就會(huì)報(bào)錯(cuò)。
【拓展訓(xùn)練】
在第3句和第4句之間插入語(yǔ)句:
04 int num=10;
或者:
04 int num; 05 num=10;
檢驗(yàn)一下程序能否運(yùn)行,是否還報(bào)錯(cuò)。
2.3 主函數(shù)
本節(jié)視頻教學(xué)錄像:9分鐘
每個(gè)C程序必須有而且只有一個(gè)主函數(shù),也就是main()函數(shù),它是程序的入口。main()函數(shù)有時(shí)也作為一種驅(qū)動(dòng),按次序控制調(diào)用其他函數(shù),C程序是由函數(shù)構(gòu)成的,這使得程序容易實(shí)現(xiàn)模塊化;main()函數(shù)后面的“()”不可省略,表示函數(shù)的參數(shù)列表;“{”和“}”是函數(shù)開始和結(jié)束的標(biāo)志,不可省略。
下圖是對(duì)主函數(shù)調(diào)用其他函數(shù)的說明。

主函數(shù)main()在程序中可以放在任何位置,但是編譯器都會(huì)首先找到它,并從它開始運(yùn)行。它就像汽車的引擎,控制程序中各部分的執(zhí)行次序。
下圖是對(duì)主函數(shù)各部分名稱的說明。

在前面的兩個(gè)范例中,主函數(shù)main()的部首都是int類型,int是整數(shù)integer單詞的縮寫,表示返回給系統(tǒng)的數(shù)據(jù)類型是整型數(shù)據(jù),返回值是0,在return語(yǔ)句中體現(xiàn)了出來。
2.4 函數(shù)定義區(qū)
本節(jié)視頻教學(xué)錄像:17分鐘
C語(yǔ)言編譯系統(tǒng)是由上往下編譯的。一般被調(diào)函數(shù)放在主調(diào)函數(shù)后面時(shí),前面就該有聲明,不然C語(yǔ)言由上往下的編譯系統(tǒng)將無(wú)法識(shí)別。正如變量必須先聲明后使用一樣,函數(shù)也必須在被調(diào)用之前先聲明,否則無(wú)法調(diào)用!函數(shù)的聲明可以與定義分離,要注意的是一個(gè)函數(shù)只能被定義一次,但可以聲明多次。
函數(shù)定義:
返回類型 函數(shù)名(參數(shù)類型1 參數(shù)名1,…,參數(shù)類型n 參數(shù)名n) { 函數(shù)體... }
例如:
int fun(int a,int b) { int c; c=a+b; return c; }
在程序中,如果main()函數(shù)在前,必須在mian()中寫函數(shù)聲明;如果函數(shù)在main()前面,可以不在main()中寫函數(shù)聲明!
下面看一個(gè)有關(guān)函數(shù)聲明和函數(shù)定義的綜合例子,比較一下它們有何不同。
#include<stdio.h> int add(int x,int y); //函數(shù)聲明語(yǔ)句 main() { int a,b,c; c=add(a,b); printf("%d",c); } int add(int x,int y)//函數(shù)定義 { int z;
z=x+y; return z; }
2.5 注釋
本節(jié)視頻教學(xué)錄像:8分鐘
讀者可能已經(jīng)注意到,很多語(yǔ)句后面都跟有“/*”和“*/”符號(hào),它們表示什么含義呢?
在前文已經(jīng)說過,我們?cè)诰庉嫶a的過程中,希望加上一些說明的文字,來表示代碼的含義,這是很有必要的。
費(fèi)了很大精力,絞盡腦汁編寫的代碼,如果沒有寫注釋或者注釋得不夠清楚,一年后又要使用這段代碼時(shí),當(dāng)年的思路全部記不得了,無(wú)奈之中,只得重分析、重理解。試問,因?yàn)楫?dāng)初一時(shí)的懶散造成了今日的結(jié)局,值得嗎?又比如,一個(gè)小組共同開發(fā)程序,別人需要在該小組寫的代碼上進(jìn)行二次開發(fā),如果代碼很復(fù)雜、沒有注釋,恐怕只能用4個(gè)字形容組員此時(shí)的心情:欲哭無(wú)淚。所以,編寫代碼時(shí)最好書寫注釋,這樣做有百利而無(wú)一弊。
注釋的要求如下。
⑴ 使用“/*”和“*/”表示注釋的起止,注釋內(nèi)容寫在這兩個(gè)符號(hào)之間,注釋表示對(duì)某語(yǔ)句的說明,不屬于程序代碼的范疇,比如【范例1-1】和【范例2-1】代碼中“/*”和“*/”之間的內(nèi)容。
⑵ “/”和“*”之間沒有空格。
⑶ 注釋可以注釋單行,也可以注釋多行,而且注釋不允許嵌套,嵌套會(huì)產(chǎn)生錯(cuò)誤,比如:
/*這樣的注釋/*特別*/有用*/
這段注釋放在程序中不但起不到說明的作用,反而會(huì)使程序產(chǎn)生錯(cuò)覺,原因是“這樣”前面的“/*”與“特別”后面的“*/”匹配,注釋結(jié)束,而“有用*/”就被編譯器認(rèn)為是違反語(yǔ)法規(guī)則的代碼。
2.6 代碼的規(guī)矩
本節(jié)視頻教學(xué)錄像:8分鐘
從書寫代碼清晰,便于閱讀、理解、維護(hù)的角度出發(fā),在書寫程序時(shí)應(yīng)遵循以下規(guī)則。
⑴ 一個(gè)說明或一個(gè)語(yǔ)句占一行。我們把空格符、制表符、換行符等統(tǒng)稱為空白符。除了字符串、函數(shù)名和關(guān)鍵字,C忽略所有的空白符,在其他地方出現(xiàn)時(shí),只起間隔作用,編譯程序?qū)λ鼈兒雎圆挥?jì)。因此在程序中使用空白符與否,對(duì)程序的編譯不產(chǎn)生影響,但在程序中適當(dāng)?shù)牡胤绞褂每瞻追梢栽黾映绦虻那逦院涂勺x性。
例如下面的代碼:
int main( ){ printf(“Hello C!\n”
); } /*這樣的寫法也能運(yùn)行,但是太亂,很不妥*/
⑵ 用“{”和“}”括起來的部分,通常表示程序某一層次的結(jié)構(gòu)。“{”和“}”一般與該結(jié)構(gòu)語(yǔ)句的第1個(gè)字母對(duì)齊,并單獨(dú)占一行。
例如下面的代碼:
int main() { printf(“Hello C!\n”); return 0;} /*這樣的寫法也能運(yùn)行,但是閱讀起來比較費(fèi)事*/
⑶ 低一層次的語(yǔ)句通常比高一層次的語(yǔ)句留有一個(gè)縮進(jìn)后再書寫。一般來說,縮進(jìn)指的是存在兩個(gè)空格或者一個(gè)制表符的空白位置。
例如下面的代碼:
int main() { printf(“Hello C!\n”); { printf(“Hello C!\n”); } return 0; }
⑷ 在程序中書寫注釋,用于說明程序做了什么,同樣可以增加程序的清晰性和可讀性。
以上介紹的4點(diǎn)規(guī)則,大家在編程時(shí)應(yīng)力求遵循,以養(yǎng)成良好的編程習(xí)慣。
2.7 高手點(diǎn)撥
本節(jié)視頻教學(xué)錄像:7分鐘
文件中聲明函數(shù),就像變量可以在頭文件中聲明,而在源文件中定義一樣,函數(shù)也可以在頭文件中聲明,在源文件中定義。把函數(shù)聲明直接放在每個(gè)使用該函數(shù)的源文件中是大多數(shù)新手習(xí)慣并喜愛的方式,這是合法的。但是這種方式古板且易出錯(cuò)。解決方法就是把函數(shù)的聲明放在頭文件中,這樣可以確保指定函數(shù)的所有聲明保持一致。如果函數(shù)接口發(fā)生變化,則只需修改其唯一的聲明即可。
將提供函數(shù)聲明的頭文件包含在定義該函數(shù)的源文件中,可使編譯器能檢查該函數(shù)的定義和聲明是否一致。特別地,如果函數(shù)定義和函數(shù)聲明的形參列表一致,但返回類型不一致,編譯器會(huì)發(fā)出警告或出錯(cuò)信息來指出差異。
那么學(xué)過了函數(shù)聲明與函數(shù)定義,它們到底有什么不同呢?我們知道函數(shù)的定義是一個(gè)完整的函數(shù)單元,它包含函數(shù)類型、函數(shù)名、形參及形參類型、函數(shù)體等,并且在程序中,函數(shù)的定義只能有一次,函數(shù)首部與花括號(hào)間也不加分號(hào)。而函數(shù)聲明只是對(duì)定義函數(shù)的返回值類型進(jìn)行說明,以通知系統(tǒng)在本函數(shù)中所調(diào)用的函數(shù)是什么類型。它不包含函數(shù)體,并且調(diào)用幾次該函數(shù)就應(yīng)在各個(gè)主調(diào)函數(shù)中作相應(yīng)聲明,函數(shù)聲明是一個(gè)說明語(yǔ)句,必須以分號(hào)結(jié)束!
學(xué)習(xí)了這一章的內(nèi)容,讀者是不是對(duì)C語(yǔ)言有更好的理解呢?下面了解一下我們?cè)谑褂煤瘮?shù)時(shí),需要注意的一些問題。
① 函數(shù)聲明可以省略形參名,但是函數(shù)定義的首部必須寫出所有形參名并給出其對(duì)應(yīng)的數(shù)據(jù)類型。
② 函數(shù)原型的主要目的是為了聲明函數(shù)返回值類型以及函數(shù)期望接受的參數(shù)的個(gè)數(shù)、參數(shù)類型和參數(shù)順序。
③ 如果程序中沒有某個(gè)函數(shù)的函數(shù)原型(沒有說明),編譯系統(tǒng)就會(huì)用第一次出現(xiàn)的這個(gè)函數(shù)(函數(shù)定義或函數(shù)調(diào)用)構(gòu)造函數(shù)原型。
④ 在默認(rèn)下,編譯系統(tǒng)默認(rèn)函數(shù)返回值為int。
在編寫函數(shù)時(shí)的常見錯(cuò)誤:當(dāng)調(diào)用的函數(shù)與函數(shù)原型不相匹配時(shí),程序會(huì)提示語(yǔ)法錯(cuò)誤,并且當(dāng)函數(shù)原型和函數(shù)定義不一致時(shí),也會(huì)產(chǎn)生錯(cuò)誤。
2.8 實(shí)戰(zhàn)練習(xí)
⒈ 要求輸入兩個(gè)整數(shù)a和b,然后再輸出這兩個(gè)數(shù)。
⒉ 輸入兩個(gè)數(shù),求兩個(gè)數(shù)的和sum以及平均數(shù)avg(float類型)。
提示:求和的公式是sum=a+b;
求平均數(shù)的公式是avg=sum/2。
************************** Very Good! **************************
⒊ 請(qǐng)參照本章例題,編寫一個(gè)C程序,輸出以下信息:
- 基于Proteus的Arduino可視化設(shè)計(jì)
- MATLAB與C/C++混合編程
- 網(wǎng)絡(luò)空間測(cè)繪技術(shù)與實(shí)踐:讓互聯(lián)網(wǎng)情報(bào)服務(wù)于網(wǎng)絡(luò)安全
- 數(shù)字化轉(zhuǎn)型架構(gòu):方法論與云原生實(shí)踐
- Android游戲開發(fā)大全
- AIDevOps:智能微服務(wù)開發(fā)、運(yùn)維原理與實(shí)踐
- 軟件架構(gòu)的藝術(shù)
- 基于Pro/Engineer Wildfire的直齒圓錐齒輪虛擬設(shè)計(jì)與制造
- 計(jì)算機(jī)網(wǎng)絡(luò)系統(tǒng)集成技術(shù)基礎(chǔ)與解決方案
- 構(gòu)建跨平臺(tái)APP:jQuery Mobile移動(dòng)應(yīng)用實(shí)戰(zhàn)(第2版) (跨平臺(tái)移動(dòng)開發(fā)叢書)
- 鋒利的jQuery
- Kubernetes Operator開發(fā)進(jìn)階
- Spring Boot+Vue 3大型前后端分離項(xiàng)目實(shí)戰(zhàn)
- React Cookbook中文版:87個(gè)案例帶你精通React框架
- 軟件項(xiàng)目管理案例教程(第5版)