#pragma和#ifndef之间有什么区别?

14
4个回答

15

#ifndef/#define/#endif技巧适用于任何C编译器,并且在某些编译器上可以加快编译过程。#pragma技巧是非标准的,只适用于少数C编译器,在不支持它的编译器中可能会导致不同的语义。


2
请注意,它支持三大编译器:GCC、MSVC和ICC。 - Billy ONeal
3
即使所有人都支持它,使用它仍然很愚蠢,因为存在一个简单的方法(#ifndef方法),它适用于所有编译器,并且对于任何了解 C 语言的人来说都是普遍熟悉的。 - R.. GitHub STOP HELPING ICE
1
@R:除非你(也许是你的团队,他们都使用相同的编译器)是项目中唯一的人。我曾经遇到过问题,当我重命名头文件但忘记更新#ifndef时。或者如果那个特定的常量被意外复制了。 - mpen
1
@Mark:可以使用UUID或者一些随机字符串,后面跟着头文件最初创建的确切日期和时间,而不是在#ifndef中使用文件名。没有使用#pragma once的借口。 - R.. GitHub STOP HELPING ICE
即使你的团队当前的编译器支持非标准扩展,那么你未来的编译器会吗?这就是非标准内容的风险所在。 - user25148

10

区别在于后者是C语言方式,前者不是。永远不要使用#pragma once,总是使用#ifndef

使用#ifndef方法时需要注意的另一件事情是,任何以两个下划线或下划线后跟大写字母开头的预处理器符号保留,不能被使用。应该使用像#ifndef MYHEADER_H这样的东西,而不是 #ifndef _MYHEADER_H


1
严格来说,#pragma 是 C 语言的一部分;甚至有一些标准的编译指示。但如果你说“不要使用 #pragma once”是正确的。 - Jonathan Leffler
但是 #pragma once 不是 C 语言的一部分。它是 #pragma 的一个实现定义用法。 - R.. GitHub STOP HELPING ICE
我想说的是,你的观点“永远不要使用#pragma”是一个夸张的说法;标准C pragma有合法的用途和C99标准 - 具体来说,#pragma STDC FP_CONTRACT ON是一个完全标准和有效的#pragma使用。然而,正如我之前所说,声明#pragma once不是标准的最好不要使用是正确的。 - Jonathan Leffler
我本意是说“永远不要使用#pragma once”。我现在已经修复了它。 - R.. GitHub STOP HELPING ICE

2

这里是关于构造的内容。

myfoo.h

#ifndef MYFOO_H
#define MYFOO_H

/* header information for myfoo.h */

#endif

应该在每个头文件中包含。诀窍是:您可以无意中多次包含头文件,而不考虑双重声明。所以这是为预处理器准备的。

#pragma是为编译器准备的,预处理器应忽略它不理解的#pragma指令。


3
我不会称其为“意外”。更可能的是头文件B和C都依赖于头文件A并且都包含它。因此,如果一个源文件包含了头文件B和C,那么它将会包含两次头文件A。 - R.. GitHub STOP HELPING ICE

1

当你需要引用一种特定的编译器(或兼容的编译器集合)来指导其代码生成时,使用 #pragma。如果你正在使用像 FP_CONTRACT-CX_LIMITED_RANGE- 这样的标准化 #pragma,那么任何符合标准的编译器都会支持。

当你要处理标准 C(或 C++)预处理器,并希望使你的代码在所有符合标准的编译器上都能运行时,请使用 #ifndef 和 ilk。

使用任何未在 C(或 C++)标准中定义的 #pragma 会使你的代码不可移植。#pragma once 是非标准 #pragma 构造中最常实现的一种例外情况。然而,它的实现在符合标准的编译器中并不普遍。而 #ifndef 则是普适的。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接