在最開(kāi)始接觸到C語(yǔ)言的時(shí)候黔夭,看到很多大牛們寫的代碼里面就有#ifndef? #define #endif 這三條語(yǔ)句,當(dāng)時(shí)不明白什么意思羽嫡,慢慢的后來(lái)自己也開(kāi)始用了本姥,也知道了他們合起來(lái)使用時(shí)為了防止頭文件被二次編譯,因?yàn)槲覀冊(cè)?jīng)寫代碼的過(guò)程中一定遇到過(guò)<.......重復(fù)定義或是重復(fù)包含>等類似的錯(cuò)誤吧杭棵。
到了學(xué)習(xí)C++的時(shí)候婚惫,我們老師給我們看他的代碼的時(shí)候發(fā)現(xiàn)他的頭文件里用的是#pragma once,就奇怪這是什么呢颜屠?然后私下百度了后才知道辰妙,這也是防止頭文件二次編譯的,然后就開(kāi)始用#pragma once了甫窟,這一用就是一個(gè)學(xué)期了密浑,后來(lái)發(fā)現(xiàn)用著很好,再也沒(méi)有重復(fù)編譯或是重復(fù)包含的錯(cuò)誤了粗井,當(dāng)時(shí)寫C++代碼的時(shí)候習(xí)慣了單個(gè)類放在獨(dú)立的頭文件里尔破,這樣子好糾錯(cuò),也好擴(kuò)展浇衬,調(diào)理更清晰懒构。
最近一段時(shí)間為了給學(xué)弟學(xué)妹們講C語(yǔ)言的知識(shí),又回過(guò)頭來(lái)看宏定義的方法耘擂。就想寫這么一篇博客來(lái)說(shuō)明一下這兩者之間的區(qū)別胆剧,過(guò)程中也百度了很多,也看了很多別人是怎么寫的醉冤,怎么認(rèn)識(shí)的秩霍。這里面肯定有他人文章中的影子,但是這絕對(duì)不是簡(jiǎn)單的復(fù)制粘貼蚁阳,而是自己看了那么多之后的思考铃绒,總結(jié)之作。
#ifndef這種是最早期使用的方法螺捐,是基于語(yǔ)言的宏定義名字不能沖突的前提下的颠悬。這種方法不僅能保證同一個(gè)頭文件不會(huì)被包含兩次,也可以保證內(nèi)容完全相同的兩個(gè)文件也只能被包含一次定血。但是他優(yōu)缺點(diǎn)赔癌,就是你的#ifndef 后面跟的宏名字和你程序中的其他宏名字發(fā)生了”撞車“,那么會(huì)出現(xiàn)以下兩種后果
第一種:file1頭文件中有一個(gè)宏
//file1.h
#define BOOK_H ? //宏名
現(xiàn)在又有一個(gè)文件 book.h 里面使用了宏定義方式防止頭文件二次編譯
#ifndef BOOK_H
#define BOOK_H
// ?program codes
#endif
下面是你的主函數(shù)所在文件內(nèi)容
#include"fil1.h"
#include"book.h" ? //這兩個(gè)都是你自己的頭文件
#include<........>
..................
預(yù)編譯階段把file1文件展開(kāi)澜沟,就得到了宏 BOOK_H届榄,在處理book.h文件時(shí)就發(fā)現(xiàn)BOOK_H這個(gè)宏已經(jīng)存在了,就不會(huì)包含book.h頭文件了倔喂,這就是弊端所在了铝条。
第二種就是:
兩者順序反過(guò)來(lái)了靖苇,弊端類似。
#pragma once這種方式班缰,是微軟編譯器獨(dú)有的贤壁,也是后來(lái)才有的,所以知道的人并不是很多埠忘,用的人也不是很多脾拆,因?yàn)樗恢С挚缙脚_(tái)。如果你想寫跨平臺(tái)的代碼莹妒,最好使用上一種名船。這是一種由編譯器提供支持的方式,防止同一文件的二次編譯旨怠,這里的同一文件指的是物理文件渠驼。
他也是有弊端的:
假如你的某一個(gè)頭文件有多份拷貝,那么這些文件雖然在邏輯上都是一樣的鉴腻,但是在物理上他們卻是不同的迷扇,所以當(dāng)你把這些文件包含的時(shí)候,就會(huì)發(fā)現(xiàn)真的都包含進(jìn)來(lái)了爽哎,然后就是編譯錯(cuò)誤了蜓席。還有,當(dāng)物理上的同一文件被嵌套包含的時(shí)候课锌,使用第一種方法預(yù)處理會(huì)每一次打開(kāi)該文件做判斷的厨内,但是第二種方法則不會(huì),所以在此#pragma once 會(huì)更快些渺贤。下面舉例說(shuō)明
// Test1.h
#ifndefine ?TEST1_H
#defineTEST1_H
...
#endif
// Test2.h
#pragma once
...
// Test.cpp
#include "Test1.h"????? // line 1
#include "Test1.h"????? // line 2
#include "Test2.h"????? // line 3
#include "Test2.h"????? // line 4 這里的Test2.h是同一物理文件
預(yù)處理器在執(zhí)行這四句的時(shí)候癣亚,先打開(kāi)Test1.h然后發(fā)現(xiàn)里面的宏TEST1_H沒(méi)有被定義,所以會(huì)包含這個(gè)文件玻孟,第二句的時(shí)候黍翎,同樣還是會(huì)打開(kāi)Test1.h的發(fā)現(xiàn)宏已定義,就不包含該文件了匣掸。第三句時(shí),發(fā)現(xiàn)之前沒(méi)有包含Test2.h則會(huì)把該文件包含進(jìn)來(lái)碰酝,執(zhí)行第四句的時(shí)候,發(fā)現(xiàn)該文件已經(jīng)被包含了铛嘱,所以不用打開(kāi)就直接跳過(guò)了