﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-gracel</title><link>http://www.cppblog.com/gracel/</link><description /><language>zh-cn</language><lastBuildDate>Tue, 09 Jun 2026 20:21:43 GMT</lastBuildDate><pubDate>Tue, 09 Jun 2026 20:21:43 GMT</pubDate><ttl>60</ttl><item><title>#pragma once和#ifndef的区别</title><link>http://www.cppblog.com/gracel/archive/2011/07/18/151301.html</link><dc:creator>grace罗</dc:creator><author>grace罗</author><pubDate>Mon, 18 Jul 2011 05:36:00 GMT</pubDate><guid>http://www.cppblog.com/gracel/archive/2011/07/18/151301.html</guid><description><![CDATA[为了避免同一个文件被include多次，C/C++中有两种方式，一种是#ifndef方式，一种是#pragma once方式。在能够支持这两种方式的编译器上，二者并没有太大的区别，但是两者仍然还是有一些细微的区别。<br />&nbsp;&nbsp;&nbsp; 方式一：<br /><span style="border-bottom: #b0b0f0 1px solid; border-left: #b0b0f0 1px solid; display: block;background: #e0e0ff; border-top: #b0b0f0 1px solid; border-right: #b0b0f0 1px solid"><span style="font-family: courier new,courier; font-size: 10pt">&nbsp;&nbsp;&nbsp; #ifndef __SOMEFILE_H__<br />&nbsp;&nbsp;&nbsp; #define __SOMEFILE_H__<br />&nbsp;&nbsp;&nbsp; ... ... // 声明、定义语句<br />&nbsp;&nbsp;&nbsp; #endif</span></span> 
<p><br />&nbsp;&nbsp;&nbsp; 方式二：<br /></p><span style="border-bottom: #b0b0f0 1px solid; border-left: #b0b0f0 1px solid; display: block;background: #e0e0ff; border-top: #b0b0f0 1px solid; border-right: #b0b0f0 1px solid"><span style="font-family: courier new,courier">&nbsp;&nbsp;<span style="font-size: 10pt">&nbsp; #pragma once<br />&nbsp;&nbsp;&nbsp; ... ... // 声明、定义语句</span></span></span> 
<p>&nbsp;&nbsp;&nbsp; #ifndef的方式受C/C++语言标准支持。它不光可以保证同一个文件不会被包含多次，也能保证内容完全相同的两个文件（或者代码片段）不会被不小心同时包含。<br />&nbsp;&nbsp;&nbsp; 当然，缺点就是如果不同头文件中的宏名不小心&#8220;撞车&#8221;，可能就会导致你看到头文件明明存在，编译器却硬说找不到声明的状况&#8212;&#8212;这种情况有时非常让人抓狂。<br />&nbsp;&nbsp;&nbsp; 由于编译器每次都需要打开头文件才能判定是否有重复定义，因此在编译大型项目时，ifndef会使得编译时间相对较长，因此一些编译器逐渐开始支持#pragma&nbsp;once的方式。</p>
<p>&nbsp;&nbsp;&nbsp; #pragma once一般由编译器提供保证：同一个文件不会被包含多次。注意这里所说的&#8220;同一个文件&#8221;是指物理上的一个文件，而不是指内容相同的两个文件。你无法对一个头文件中的一段代码作pragma once声明，而只能针对文件。<br />&nbsp;&nbsp;&nbsp; 其好处是，你不必再费劲想个宏名了，当然也就不会出现宏名碰撞引发的奇怪问题。大型项目的编译速度也因此提高了一些。<br />&nbsp;&nbsp;&nbsp; 对应的缺点就是如果某个头文件有多份拷贝，本方法不能保证他们不被重复包含。当然，相比宏名碰撞引发的&#8220;找不到声明&#8221;的问题，这种重复包含很容易被发现并修正。</p>
<p>&nbsp;&nbsp;&nbsp; #pragma once方式产生于#ifndef之后，因此很多人可能甚至没有听说过。目前看来#ifndef更受到推崇。因为#ifndef受C/C++语言标准的支持，不受编译器的任何限制；而#pragma once方式却不受一些较老版本的编译器支持，一些支持了的编译器又打算去掉它，所以它的兼容性可能不够好。一般而言，当程序员听到这样的话，都会选择#ifndef方式，为了努力使得自己的代码&#8220;存活&#8221;时间更久，通常宁愿降低一些编译性能，这是程序员的个性，当然这是题外话啦。</p>
<p>&nbsp;&nbsp;&nbsp; 还看到一种用法是把两者放在一起的：</p><span style="border-bottom: #b0b0f0 1px solid; border-left: #b0b0f0 1px solid; display: block;background: #e0e0ff; border-top: #b0b0f0 1px solid; border-right: #b0b0f0 1px solid"><span style="font-family: courier new,courier">&nbsp;&nbsp;&nbsp; #pragma once<br />&nbsp;&nbsp;&nbsp; #ifndef __SOMEFILE_H__<br />&nbsp;&nbsp;&nbsp; #define __SOMEFILE_H__<br />&nbsp;&nbsp;&nbsp; ... ... // 声明、定义语句<br />&nbsp;&nbsp;&nbsp; #endif</span></span> 
<p>&nbsp;&nbsp;&nbsp; 看起来似乎是想兼有两者的优点。不过只要使用了#ifndef就会有宏名冲突的危险，也无法避免不支持#pragma once的编译器报错，所以混用两种方法似乎不能带来更多的好处，倒是会让一些不熟悉的人感到困惑。</p>
<p>&nbsp;&nbsp;&nbsp; 选择哪种方式，应该在了解两种方式的情况下，视具体情况而定。只要有一个合理的约定来避开缺点，我认为哪种方式都是可以接受的。而这个已经不是标准或者编译器的责任了，应当由程序员自己或者小范围内的开发规范来搞定。</p>
<p>&nbsp;&nbsp;&nbsp; btw：我看到GNU的一些讨论似乎是打算在GCC 3.4（及其以后？）的版本取消对#pragma once的支持。不过事实上，我手上的GCC 3.4.2和GCC 4.1.1仍然支持#pragma once，甚至没有deprecation warning，倒是GCC2.95会对#pragma once提出warning。<br />&nbsp;&nbsp;&nbsp; VC6及其以后版本亦提供对#pragma once方式的支持，这一特性应该基本稳定下来了。&nbsp;</p><script type="text/javascript">
if ($ != jQuery) {
	$ = jQuery.noConflict();
}
var isLogined = false;
var cb_blogId = 54438;
var cb_entryId = 1425604;
var cb_blogApp = "hokyhu";
var cb_blogUserGuid = "0c0abbed-4219-de11-9510-001cf0cd104b";
var cb_entryCreatedDate = '2009/3/30 23:56:00';
</script><img src ="http://www.cppblog.com/gracel/aggbug/151301.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/gracel/" target="_blank">grace罗</a> 2011-07-18 13:36 <a href="http://www.cppblog.com/gracel/archive/2011/07/18/151301.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>