1. 程式人生 > >標頭檔案保護符和#pragma once #pragma once與 #ifndef的區別

標頭檔案保護符和#pragma once #pragma once與 #ifndef的區別

為了避免同一個檔案被include多次

1   #ifndef方式
2   #pragma once方式

在能夠支援這兩種方式的編譯器上,二者並沒有太大的區別,但是兩者仍然還是有一些細微的區別。
    方式一:

    #ifndef __SOMEFILE_H__
    #define __SOMEFILE_H__
    ... ... // 一些宣告語句
    #endif

    方式二:

    #pragma once
    ... ... // 一些宣告語句


   #ifndef的方式受C/C++語言標準支援。它不光可以保證同一個檔案不會被包含多次,也能保證內容完全相同的兩個檔案(或者程式碼片段)不會被不小心同時包含。
    當然,缺點就是如果不同標頭檔案中的巨集名不小心“撞車”,可能就會導致你看到標頭檔案明明存在,編譯器卻硬說找不到宣告的狀況——這種情況有時非常讓人抓狂。
    由於編譯器每次都需要開啟標頭檔案才能判定是否有重複定義,因此在編譯大型專案時,ifndef會使得編譯時間相對較長,因此一些編譯器逐漸開始支援#pragma once的方式。

    #pragma once一般由編譯器提供保證:同一個檔案不會被包含多次。注意這裡所說的“同一個檔案”是指物理上的一個檔案,而不是指內容相同的兩個檔案。你無法對一個頭檔案中的一段程式碼作pragma once宣告,而只能針對檔案。
    其好處是,你不必再費勁想個巨集名了,當然也就不會出現巨集名碰撞引發的奇怪問題。大型專案的編譯速度也因此提高了一些。
    對應的缺點就是如果某個標頭檔案有多份拷貝,本方法不能保證他們不被重複包含。當然,相比巨集名碰撞引發的“找不到宣告”的問題,這種重複包含很容易被發現並修正。

    #pragma once方式產生於#ifndef之後,因此很多人可能甚至沒有聽說過。目前看來#ifndef更受到推崇。因為#ifndef受C/C++語言標準的支援,不受編譯器的任何限制;而#pragma once方式卻不受一些較老版本的編譯器支援,一些支援了的編譯器又打算去掉它,所以它的相容性可能不夠好。一般而言,當程式設計師聽到這樣的話,都會選擇#ifndef方式,為了努力使得自己的程式碼“存活”時間更久,通常寧願降低一些編譯效能,這是程式設計師的個性,當然這是題外話啦。

    還看到一種用法是把兩者放在一起的:

    #pragma once
    #ifndef __SOMEFILE_H__
    #define __SOMEFILE_H__
    ... ... // 宣告、定義語句
    #endif

    看起來似乎是想兼有兩者的優點。不過只要使用了#ifndef就會有巨集名衝突的危險,也無法避免不支援#pragma once的編譯器報錯,所以混用兩種方法似乎不能帶來更多的好處,倒是會讓一些不熟悉的人感到困惑。

    選擇哪種方式,應該在瞭解兩種方式的情況下,視具體情況而定。只要有一個合理的約定來避開缺點,我認為哪種方式都是可以接受的。而這個已經不是標準或者編譯器的責任了,應當由程式設計師自己或者小範圍內的開發規範來搞定。

    btw:我看到GNU的一些討論似乎是打算在GCC 3.4(及其以後?)的版本取消對#pragma once的支援。不過事實上,我手上的GCC 3.4.2和GCC 4.1.1仍然支援#pragma once,甚至沒有deprecation warning,倒是GCC2.95會對#pragma once提出warning。
    VC6及其以後版本亦提供對#pragma once方式的支援,這一特性應該基本穩定下來了。 

相關推薦

檔案護符#pragma once #pragma once #ifndef區別

為了避免同一個檔案被include多次 1   #ifndef方式 2   #pragma once方式 在能夠支援這兩種方式的編譯器上,二者並沒有太大的區別,但是兩者仍然還是有一些細微的區別。     方式一:     #ifndef __SOMEFILE_H__     #define __SOMEFIL

檔案的編寫引用

      我用的是 Dev-c++  編寫標頭檔案     首先寫標頭檔案裡面的函式,       然後儲存,記得字尾寫  .h   就行   例:(順序表的標

ubuntu中找不到檔案term.hcurses.h的解決方法

創建於 2012-05-16 收藏自個人的百度空間 -------------------------------- 當/usr/include中沒有term.h和curses.h時,包含這兩個標頭檔案的程式會如下報錯: term.h: 沒有那個檔案或目錄 curses.h

檔案重複包含變數重複定義

在c或c++中,標頭檔案重複包含問題是程式設計師必須避免的問題,也是很多新手容易犯錯的問題。為什麼要避免標頭檔案重複包含呢?        1.我們知道在編譯c或c++程式時候,編譯器首先要對程式進行預處理,預處理其中一項工作便是將你源程式中#include的標頭檔案完整的展

關於c++裡面引用檔案尖括號雙引號的使用

今天寫資料庫,因為用的是mysql自帶的c api。設計到庫的匯入和標頭檔案的匯入。 用include 引用標頭檔案時,雙引號和尖括號的區別: 1.雙引號:引用非標準庫的標頭檔案,編譯器首先在程式原始檔所在目錄查詢,如果未找到,則去系統預設目錄查詢,通常用於引用使

檔案windows.h巨集定義而引發的錯誤

先看下面一段程式碼:#define _CRT_SECURE_NO_WARNINGS 1 #define N 6 #include<stdio.h> #include<Windows.h> int main() { printf("%d \n",

預編譯檔案的作用使用方法介紹

預編譯頭的概念: 所謂的預編譯頭就是把一個工程中的那一部分程式碼,預先編譯好放在一個檔案裡(通常是以.pch為副檔名的),這個檔案就稱為預編譯標頭檔案這些預先編譯好的程式碼可以是任何的C/C++程式碼--------甚至是inline的函式,但是必須是穩定的,在工程開發的過

保證檔案只被編譯一次的方法#pragma once#ifndef

#ifndef ABC_H #define ABC_H #endif 和 #pragma once 這兩種方法都可以保證所在標頭檔案只被編譯一次,區別是#pragma once比較新,在一些老編譯器上

關於extern以及原始檔檔案的應用

最近在糾結這個問題,全域性變數的宣告到底應該在原始檔還是標頭檔案中,其實有兩種方法: 緣由:因為 int a;表示的是一個定義,而extern int a;卻是一個宣告 方法一:在a.h中表示全域性變數的宣告:extern int a;       &nbs

VC 6 0中新增庫檔案檔案

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!        

Linux中C/C++編譯新增檔案庫路徑方式

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!        

【Keil】Keil5新增源程式檔案

xxx.c就是源程式 xxx.h就是標頭檔案   【源程式新增方法】 雙擊資料夾,例如圖片上的Source,跳出彈窗,選擇需要新增的源程式即可   【新增標頭檔案的方法】 1.首先點選圖片紅框處,或是在資料夾test點選右鍵,再不然點選快捷鍵Alt+F7 2.跳出O

spring xml檔案xmlnsxsi的意思

                        在spring的

KEIL 檔案路徑#include區別

KEIL 標頭檔案路徑可以直接寫在引號內,預設的話,標頭檔案必須在工程檔案同一個目錄下,比如: #include<ds0832.h> //此時ds0832.h 檔案必須與工程檔案同一目錄 #include "d:\myfile\ds0832.h" //此時 ds0832.h檔案在d:\m

檔案不帶.h的區別

所有C++標準庫的標頭檔案都是沒有.h結尾的。這麼做是為了區分,C標準庫的標頭檔案和C++標準庫的標頭檔案。比如最具代表性的: #include <string.h> // C 標準庫標頭檔案,包含 strlen,memset 等函式 #include <string>

CodeBlocks 17.12 工程如何引用其他資料夾的檔案源程式

假設你的工程名為project,目錄為F:\test。但是你想在project中使用資料夾F:\library下面的一些標頭檔案和源程式。由於這些標頭檔案和源程式與工程project不在同一目錄下面,所以需要做一些設定。下面介紹兩種方法:     1、第一步:在CodeBlocks介面中

Qt新增庫檔案檔案目錄(QCreator)(轉載學習)

在使用QtCreator開發影象處理程式的時候想加入Opencv庫來處理圖形,新增標頭檔案,需要編輯工程資料夾下的.pro檔案在檔案中新增以下內容,即可包含標頭檔案的資料夾:   INCLUDEPATH +=D:\OpenCV2.0\vc2008\include

檔案原始檔工程構建CMakeLists寫法

1.最簡單的CMakeLists.txt如下,只有一個原始檔: cmake_minimum_required (VERSION 2.6) #版本要求 project (Tutorial) #工程名稱 add_executable(

C++學習筆記 — 理解檔案(.h)原始檔(.cpp)

原始檔根據#include來關聯檔案 系統自帶的檔案用尖括號括起來,編譯器會在系統檔案目錄下查詢 #include <> 使用者自定義的檔案用雙括號括起來,編譯器首先在使用者目錄下查詢,然

C語言中,檔案原始檔的關係(轉)

//a.h void foo(); //a.c #include "a.h"   //我的問題出來了:這句話是要,還是不要? void foo() {      return; } //main.c #include "a.h" int main(int argc