C++ Header Guard 簡介


Posted by Po-Jen on 2017-09-30

前言

C++ 的 header guard (中文譯作表頭哨兵,聽起來超帥) 是在開源/大型專案中常常用到的功能,所以如果想要踏入開源專案的世界,看到 header guard 就覺得親切熟悉,絕對可以幫助你更把心思放在體會到這些開源程式碼的美!

而且這個例子正巧是有朋友去面試美國某間新創公司時,實際被問到的問題,所以才興起想要動筆寫下這篇文章的念頭。畢竟很多小地方有沒有真正弄通是技術實力紮不紮實的重要指標!

我剛剛隨便選了一個 C++ 的開源專案 (Point Cloud Library) 的 header 檔,裡面就有用到

#ifndef PCL_PEOPLE_PERSON_CLASSIFIER_H_
#define PCL_PEOPLE_PERSON_CLASSIFIER_H_

#include <pcl/people/person_cluster.h>
#include <pcl/people/hog.h>

...

#include <pcl/people/impl/person_classifier.hpp>
#endif /* PCL_PEOPLE_PERSON_CLASSIFIER_H_ */

預處理器簡介

首先我們需要對 header file 的使用有個初步的認識,這就不能不介紹一下預處理器。我們都知道,要使用 header file 就是要在程式碼中 #include 它,而 #include 就是預處理器的一部分。

預處理器存在的目的是為了處理程式碼內的文本,例如 header file 的內容,之所以稱做 "預" 處理器是因為他在編譯氣執行之前就會先做事了。以 header file 的例子來說,預處理器會以 header file 的內容取代 #include 那一行。

那為何需要 header guard

原因是,header file 也常常需要 #include 其他 header file,例如寫程式時可能會寫到如下的程式碼:

main.cpp:

#include <string>
#include "myHeader1.h"
#include "myHeader2.h"
...

myHeader1.h:

#include <string>
...

如果在 myHeader1.h 裡面也需要用到 string,那可想而知經過預處理器的處理後,main.cpp 裡面就會有兩次 #include <string>,但這種情況根本超級常見啊,我們總不可能都去檢查過 myHeader1.h、myHeader2.h 跟他們 include 的所有 header file 再決定自己要不要 #include <string> 吧。所以就要有個機制,讓 header file 即便被 include 多次,也不會有其內定義的 classes 和 objects 被多次定義。而通常,我們就是用 header guard 來做這件事。

header guard 怎麼運作

這時候就讓我們再回過頭來看看前言提到的例子:

#ifndef PCL_PEOPLE_PERSON_CLASSIFIER_H_
#define PCL_PEOPLE_PERSON_CLASSIFIER_H_

#include <pcl/people/person_cluster.h>
#include <pcl/people/hog.h>

...

#include <pcl/people/impl/person_classifier.hpp>
#endif /* PCL_PEOPLE_PERSON_CLASSIFIER_H_ */

這邊使用到的是名為預處理器變數(preprocessor variables)的東西,在此例中為 PCL_PEOPLE_PERSON_CLASSIFIER_H_,而預處理器變數只有兩種狀態;已定義和未定義。所以上面的寫法就是用 #ifndef 來判斷是否已經定義過 PCL_PEOPLE_PERSON_CLASSIFIER_H_,如果沒有,那就先定義 PCL_PEOPLE_PERSON_CLASSIFIER_H_,然後才 #include 後面的東西。

看到這邊讀者們應該不難推敲,只要在需要 #include 的地方都加上類似的預處理器變數檢查,那就只有在預處理器變數還沒被定義時才會 #include,一旦被定義過了,就不會再重複定義了。

再回過頭來,如果你去看 string.h 的內容,你就會看到:

#ifndef _STRING_H_
#define _STRING_H_ 1
...

這樣一切就都串起來了!

總結

以前在學生時代學習程式語言的時候,常常會有學了某個東西不知道好用在哪裡的感覺,header guard 就是一個好例子。透過開源專案,我們很容易欣賞到某個功能的美,也希望大家看完這篇之後,每次看到 header guard 都能感覺世界真美好 XD

關於作者:
@pojenlai 演算法工程師,對機器人跟電腦視覺有>少許研究,最近在學習看清事物的本質與改進自己的觀念


#C++ #header file #header guard









Related Posts

筆記、Single Page Application

筆記、Single Page Application

猜數字

猜數字

How to Set Up Firewall with UFW on Ubuntu 20.04

How to Set Up Firewall with UFW on Ubuntu 20.04




Newsletter




Comments