c語言入門23,一文弄懂為什麼要使用指針,看完還不懂,你踢我

編程語言 C語言 西部數據 程序員 高射炮 嵌入式時代 2018-11-29

在開始討論為什麼使用 C 語言指針之前,先介紹一下複雜點的指針,這是新知識,也是鋪墊。不想看鋪墊可以往後翻一翻。

前面幾節介紹了 C 語言中指針,也討論了數組指針指針數組的區別,但歸根結底,至今我們說的都是基礎數據類型定義的指針,C 語言有複合數據類型,那麼它有複合數據類型的指針嗎?答案是肯定的,事實上,在 C 語言中複合類型指針的使用相當廣泛。

c語言入門23,一文弄懂為什麼要使用指針,看完還不懂,你踢我

先來看看結構體指針。還是從實例出發,我們定義一個結構體類型,它有兩個成員,分別是 sleep_time(睡覺時間) 和 work_time(工作時間),然後定義這種結構體類型的變量和指針:

struct week{
double sleep_time;
double work_time;
};
struct week w;
struct week *pw = &w;

可以通過結構體指針 pw 訪問 week 結構體的成員:

(*pw).sleep_time = 7.0;

這樣寫有點麻煩,因此 C 語言非常貼心的提供了“->”運算符,所以我們還可以這樣通過結構體指針訪問成員:

pw->sleep_time = 7.0;
c語言入門23,一文弄懂為什麼要使用指針,看完還不懂,你踢我

為什麼要使用 C 語言中的指針

好了,現在我們已經知道 C 語言中的結構體指針怎麼使用了,鋪墊完了。但是,明明使用結構體變量 w 就能很好的讀寫 week 結構體啊,為什麼要用結構體指針呢?這不是麻煩了嗎?

為什麼要使用結構體指針,其實可以延伸到“為什麼要使用指針”,本節將以結構體指針為例討論一下這個問題。

是的,僅僅訪問 week 的 sleep_time 成員,只使用結構體變量 w 就足夠了,再通過 pw 訪問真的麻煩了。但是工具會不會帶來方便,要看我們怎麼使用,不能因為高射炮打蚊子不方便就說高射炮沒用。恰當的使用結構體指針,有利於我們寫出更加緊湊,效率更高的 C 程序。

一週有五天工作日,兩天週末,一般來說,在工作日(weekday),人們的睡覺時間較短,工作時間較長,所以我們定義 weekday 函數來規劃工作日的時間:

void weekday(struct week wd)
{
wd.sleep_time = 7.0; // 7 小時
wd.work_time = 8.5; // 8.5 小時
}

而在週末(weekend)則反過來,工作間較短,睡覺時間較長,所以我們定義 weekend 函數來規劃週末的時間:

c語言入門23,一文弄懂為什麼要使用指針,看完還不懂,你踢我

void weekend(struct week we)
{
we.sleep_time = 9.0; // 9 小時
we.work_time = 2.5; // 2.5 小時
}

這兩個函數很好的規劃了一週的睡覺和工作時間,但是卻並不好用。為什麼呢?因為它倆只在自己內部規劃了,我們外界看不到啊!想在 main 函數把規劃好的時間打印出來都辦不到,因為它倆在自己內部規劃好以後,就把“規劃書”銷燬了。

這裡把 weekday 和 weekend 函數的局部變量比作“規劃書”,函數退出後,局部變量就自動銷燬了。可以參考《c語言入門5,一文徹底弄懂函數的形參和實參》一節。

可能你會說,那我可以把“規劃書”返回給 main 函數啊,讓 weekday 和 weekend 函數有返回值就可以了:

struct week weekday(struct week wd)
{
wd.sleep_time = 7.0; // 7 小時
wd.work_time = 8.5; // 8.5 小時
return wd;
}
struct week weekend(struct week we)
{
we.sleep_time = 9.0; // 9 小時
we.work_time = 2.5; // 2.5 小時
return we;
}
int main()
{
struct week w;
w = weekday(w);
printf("weekday, sleep time: %0.1f, work time: %0.1f\n",
w.sleep_time, w.work_time);
weekend(w);
printf("weekend, sleep time: %0.1f, work time: %0.1f\n",
w.sleep_time, w.work_time);
return 0;
}

是的,這的確是一個解決問題的辦法,main 可以把 weekday 和 weekend 函數的“規劃書”打印出來了。

c語言入門23,一文弄懂為什麼要使用指針,看完還不懂,你踢我

但是這種解決問題的辦法有一點臃腫,很多程序員把這樣的代碼稱為“不優雅”的代碼。你看,main 現在有一份空的“規劃書”,需要 weekday 和 weekend 函數處理。weekday 和 weekend 函數能處理,但是它們要複製一份“規劃書”回到自己內部做,這種複製就造成了空間浪費。此外,weekday 和 weekend 函數做完了規劃書,還要把“規劃書”再從自己內部取出,return 給 main,這就有時間浪費

c語言入門23,一文弄懂為什麼要使用指針,看完還不懂,你踢我

更節約資源,更有效率的做法是:weekday 和 weekend 函數處理這份“規劃書”時,直接處理 main 裡的“規劃書”就可以了。不要複製後再處理,完事了還要在從自己內部傳出。那,weekday 和 weekend 函數應該怎麼修改呢?請看:

void weekday(struct week *wd)
{
wd->sleep_time = 7.0; // 7 小時
wd->work_time = 8.5; // 8.5 小時
}
void weekend(struct week *we)
{
we->sleep_time = 9.0; // 9 小時
we->work_time = 2.5; // 2.5 小時
}
int main()
{
struct week w;
weekday(&w);
printf("weekday, sleep time: %0.1f, work time: %0.1f\n",
w.sleep_time, w.work_time);
weekend(&w);
printf("weekend, sleep time: %0.1f, work time: %0.1f\n",
w.sleep_time, w.work_time);
return 0;
}

看到了沒,利用指針,整個 C 代碼簡潔多了。weekday 和 weekend 函數接收到的參數都是 main 裡結構體變量 w 的地址,所以它倆都是直接操作 w 的。這樣就不用在自己的棧幀裡複製一份 w 再處理了,也不用在處理完畢還要 return 給 main 了。

c語言入門23,一文弄懂為什麼要使用指針,看完還不懂,你踢我

看到這裡,你可能會說,什麼嘛,不就是用指針代替了結構體做參數嗎?指針說不定比結構體還要耗空間呢!對嗎?一起來看下:結構體變量 w,它佔用內存至少兩個 sizeof(double) 的空間(一個 double 型數據通常佔用 8 字節空間)。而一個指針,不管它是什麼類型的,在大多數 32 位計算機中,它只佔 4 字節空間,在大多數 64 位計算機中,它也僅僅佔 8 字節空間。所以使用指針做 weekday 和 weekend 函數的參數,在空間上,絕對是比直接使用 week 結構體節約空間的,何況指針還提升了效率,簡潔了代碼。

如果是一個 char 型變量,它只佔用 1 字節空間,這時使用指針的確更浪費空間。但是如果是一個非常複雜的結構體,它佔用的內存空間甚至達幾千字節,這時使用指針就非常節約空間了。所以說,工具是死的,人是活的。

c語言入門23,一文弄懂為什麼要使用指針,看完還不懂,你踢我

到這裡,相信你已經瞭解 C 語言指針在節約空間,提升程序效率方面的作用了。事實上,這裡我們介紹的僅僅是指針的冰山一角,在以後的文章裡,你會愈發覺得 C 語言指針的強大的。


歡迎在評論區一起討論,質疑。文章都是手打原創,每天最淺顯的介紹C語言,喜歡我的文章就關注一波吧,可以看到最新更新和之前的文章哦。

(私信我發送“嵌入式時代”,可以深入討論。)

相關推薦

推薦中...