第四十二章 隱身和顯形
聽到「隱身術(shù)」三個(gè)字,我和小弦子眼里瞬間就開始放光,就連旁聽的六叔叔注意力都集中了幾分。
就在我們都靜等老爹下文的時(shí)候,老爹卻偏偏不著急講了,又是喝水,又是擦眼鏡什么的,一幅不慌不忙的樣子,恨得我牙根兒都癢癢。
吊足了我們的胃口后,老爹這才回到自己的電腦旁邊徐徐說道:「一直以來,因?yàn)槲覀兊某绦蚬δ鼙容^簡(jiǎn)單,所以程序里面就只有一個(gè).c文件,但是隨著我們的程序越來越復(fù)雜,如果還把所有代碼都放在一個(gè).c文件中就顯得特別臃腫,不方便閱讀。
其實(shí)推箱子這個(gè)程序已經(jīng)暴露出來這個(gè)問題了,有時(shí)候我們需要查看某行代碼的時(shí)候,往往要翻閱很久。
于是乎我們就要對(duì)程序的功能進(jìn)行分塊,各個(gè)塊完成相應(yīng)的一些小功能。最后把小功能組合在一起,就完成了一個(gè)大的功能了。
為了方便管理和閱讀,一般我們就會(huì)按塊來創(chuàng)建.c文件,也就是說,程序中可能會(huì)存在多個(gè).c文件。
在默認(rèn)情況下,我們定義在一個(gè).c文件的全局變量毫無秘密可言,因?yàn)槠渌?c文件可以通過一個(gè)關(guān)鍵字——external讓它顯出真身,然后就可以肆無忌憚地把它的臉按在地板上摩擦。
比如說我們?cè)趜hangsan.c文件里聲明了一個(gè)全局變量:
int heart = 10;
然后還有一個(gè)lisi.c文件,它想看看zhangsan.c中的heart是什么,于是它就在自己聲明全局變量的地方寫了這么一句:
external int heart;
這個(gè)時(shí)候在lisi.c中就能對(duì)zhangsan.c中的heart為所欲為了。
那這樣會(huì)不會(huì)有什么問題么?」
老爹拋出了他的疑問。我和小弦子對(duì)視了一眼,相互搖了搖頭。
問題肯定是有的嘛,不然老爹怎么可能會(huì)無的放矢,跟我們扯這么多有的沒的。
「既然你們想不到,那我就給你們?cè)O(shè)置個(gè)場(chǎng)景。
假設(shè)我們把一個(gè).c文件比作是一個(gè)人,那么.c文件中的變量就是我們身體的器官。像手啊,腳啊,這種類型的器官暴露在外面倒是沒什么,甚至讓人摸兩下也沒什么大問題。
可是像我們的心臟這類器官能夠暴露在外面么?哪天隨便來個(gè)人跟我們說,讓我們把心臟給Ta看看,摸兩下,你說這讓不讓人害怕?
所以基于安全等各方面的因素,心臟這類的器官必須藏起來,不能雖然讓人觸碰。
人生在世,誰還沒有點(diǎn)小秘密了?.c文件也是一樣的啊,總得有點(diǎn)自己隱私吧?
所以說啊,如果我們讓一個(gè)全局變量只能在當(dāng)前.c文件,也就是聲明這個(gè)變量的.c文件中能夠使用,就用static關(guān)鍵字修飾它。一旦一個(gè)全局變量被static關(guān)鍵字修飾,那么其它的.c文件就不能在使用external關(guān)鍵字獲取了。
換句話說,被static修飾的全局變量就在其它.c文件面前消失了,這個(gè)就是static的隱身功能。
有一點(diǎn)要注意啊,剛剛說的內(nèi)容都是針對(duì)的全局變量,如果是局部變量根本就不存在這個(gè)問題。」
我和小弦子若有所得,就連旁聽的六叔叔居然都露出一副「原來如此」的表情。
「static除了能夠修飾全局變量,還可以修飾函數(shù)哦。同樣的道理,如果一個(gè)函數(shù)被static修飾了,那么這個(gè)函數(shù)也就只能在定義它的.c文件中使用了。
對(duì)于函數(shù)而言,如果要在其它的.c文件中調(diào)用它就不能靠external關(guān)鍵字了,而是要靠頭文件,也就是.h文件。
還記得我們每一個(gè)程序都要寫的#include<stdio.h>么?stdio.h就是一個(gè)頭文件。
好了,光說不練假把式,那接下來我就用代碼給你們演示一遍。
假設(shè)我們有一個(gè)專門對(duì)圓進(jìn)行計(jì)算的功能模塊,于是定義一個(gè)circle.c,內(nèi)容如下:
double PI = 3.1415926;
double circleMianJi(double r)
{
return PI * r * r;
}
double circleZhouChang(double r)
{
return 2 * PI * r;
}
如果要讓circleMianJi和circleZhouChang這兩個(gè)方法能夠在其他.c文件中調(diào)用,這個(gè)時(shí)候我們就要再創(chuàng)建一個(gè)xxx.h文件,并且將這兩個(gè)函數(shù)的聲明部分放在那個(gè)xxx.h文件中。
這個(gè)時(shí)候xxx.h和circle.c還沒有任何關(guān)系,所以我們需要在circle.h中包含xxx.h,這樣它們才會(huì)建立起聯(lián)系。
有一點(diǎn)要注意,包含一個(gè)我們自己定義的.h文件就不能再用<>了,而要用雙引號(hào),為了方便表示,我們就新建一個(gè)circle.h:
#include
double circleMianJi(double r);
double circleZhouChang(double r);
然后circle.c的內(nèi)容也要作出相應(yīng)變化:
#include “circle.h“
double PI = 3.1415926;
double circleMianJi(double r)
{
return PI * r * r;
}
double circleZhouChang(double r)
{
return 2 * PI * r;
}
現(xiàn)在如果我們需要在其他.c文件中調(diào)用circleMianJi和circleZhouChang這兩個(gè)方法的話,就只需要包含circle.h即可,現(xiàn)在我們要在包含main函數(shù)的main.c文件中調(diào)用:
#include
#include “circle.h“
int main(int argc, char const *argv[])
{
double r = 5;
double mianJi = circleMianJi(r);
double zhouChang = circleZhouChang(r);
printf(“半徑為%.2f 的圓面積為%.2f\n“, r, mianJi);
printf(“半徑為%.2f 的圓周長(zhǎng)為%.2f\n“, r, zhouChang);
getchar();
return 0;
}
如果我們想要在main.c中讀寫circle.c的PI變量,則只需要在聲明全局變量的地方寫一句:
external double PI;
就可以了,記住,使用external的時(shí)候不能對(duì)變量進(jìn)行初始化!
同樣的,如果circle不想PI被其他.c文件讀寫,只需要加上static就好了。
同理,如果不想circleMianJi和circleZhouChang這兩個(gè)方法被其他.c文件調(diào)用,只需要在circle.h中聲明它們時(shí)加static即可。當(dāng)然了,函數(shù)實(shí)現(xiàn)和聲明必須保持一致,既然聲明那兒加了static,實(shí)現(xiàn)的地方也必須加上!
circle.h文件:
#include
static double circleMianJi(double r);
static double circleZhouChang(double r);
circle.c文件:
#include “circle.h“
static double PI = 3.1415926;
static double circleMianJi(double r)
{
return PI * r * r;
}
static double circleZhouChang(double r)
{
return 2 * PI * r;
}」
老爹通過投影儀給我們演示了一遍,基本上沒有什么難度。
「原來咱們編譯的時(shí)候針對(duì)的是單個(gè).c文件,現(xiàn)在文件變多了,編譯命令也會(huì)有所改變。
gcc *.c -o xxxx
*.c的意思是編譯當(dāng)前文件加下所有的.c文件,最后生成一個(gè)名為xxxx的可執(zhí)行文件。當(dāng)然了,你們有興趣的話也可以這樣:
gcc circle.c main.c -o mian
把所有的.c文件都一一羅列出來。
不過當(dāng).c文件比較多的時(shí)候就比較好玩兒了。
至此,和函數(shù)相關(guān)的知識(shí)我們就差不多講完了。這部分理論知識(shí)比較多,也比較抽象,需要你們結(jié)合實(shí)際代碼多理解。
同時(shí),也恭喜你們升級(jí)了,從小菜鳥升級(jí)到了菜鳥。
相信有了這么多的知識(shí)積累,你們已經(jīng)能夠?qū)懗龊芏嘤杏玫某绦騺砹?。同時(shí)你們對(duì)C語言的世界應(yīng)該也有了一個(gè)大概的輪廓了,但是想要在這個(gè)世界中飛翔還差一段距離。
明天,我會(huì)和你們一起學(xué)習(xí)C語言最為中的精髓部分——指針。當(dāng)學(xué)完這一部分,你們就成長(zhǎng)為了真正的鳥,基本上能夠在C語言世界中自由飛翔了。」