在C语言中,#import和#include有什么区别?

15

我研究了一些预处理器指令,发现在C程序中有时会使用 #import。但是我不确定它与 #include 之间的区别,一些网站说 #include 只用于头文件,而 #import 更多地用于 Java 且在 C 中已被弃用。

如果是这样的话,为什么还有一些程序使用 #import,它到底与 #include 有何不同?此外,我在我的一些 C 程序中使用了 #import,它似乎能正常工作并且与 #include 有相同的作用。


6
#import 不是标准的 C 语言,因此回答这个问题有点困难。 - Oliver Charlesworth
2
#import在标准C中并没有被废弃,因为它从来都不是标准C或K&R C的任何版本的一部分。 - John Bollinger
1
@JohnBollinger:是的。不幸的是,cpp手册(在gcc发行版中)将其称为“已弃用”,因为它是Objective-C的一部分,因此许多cpp实现确实实现了它。但是您可以弃用扩展,这是一种说“这个扩展将永远不会成为标准”的方式。这在ECMAscript中很常见,在C家族中也不是未知的。 - rici
@JohnBollinger:C语言在C89之前主要是通过先例来定义的,而在20世纪90年代流行起来的语言是C89和填补其中空缺的有用先例的组合超集。标准承认先例的存在但将其视为“已弃用”比通常对待曾经普遍存在于大多数实现中但并非所有实现的行为更好。 - supercat
3个回答

11

这在Gnu CPP(C预处理器)手册中有很好的解释,尽管clang的行为是相同的(可能还有其他C编译器,但不包括MSVC):

  1. 问题。简述:通常不希望将同一头文件包含两次到单个翻译单元中,因为这会导致重复声明,这是一个错误。然而,由于包含的文件本身可能想要包含其他文件,因此很难避免。

  2. 一些非标准解决方案(包括#import)。简述:在包含文件中使用#pragma once和在包含在内文件中使用#import都可以防止重复包含。但是,#pragma once是一个更好的解决方案,因为引入者不应该知道重复包含是否可接受。

链接文档将#import称为“已弃用的扩展”,这是一种略微奇怪的描述方式,因为该功能从未成为任何标准C版本的一部分。但这并不完全没有意义:许多预处理器实现确实允许使用#import(这是Objective-C的一个特性),因此它是一种常见的扩展。称其为已弃用是一种说法,即无论实现有多少普及,该扩展都将永远不会成为任何C标准的一部分。

如果要使用扩展,请使用#pragma once;可能将来也不会在某些头文件中使用,但是将其更改为给定头文件仅需要在一个位置进行更改,而不是在包含头文件的每个文件中进行更改。 C++甚至C可能最终会开发某种模块功能,这将允许替换包含保护。


所以 #import 仍然可以使用,因为它是 C 的其他派生语言(如 Objective-C)的一部分,但它本身并不是 C 的本地语言? - AkThao
如果你正在使用一个编译器,其预处理器也支持Objective-C,那么这将是可行的。但是它不适用于微软编译器,例如f9e。 - rici
哦,这样就更有意义了,所以基本上就是编译器已经拥有和知道的内容。 - AkThao
@rici,我不是很理解你的意思:“但是#pragma once是一个更好的解决方案,因为包含者不应该知道重复包含是否可接受”。您能否对此发表评论? - Alexander
@alexander:并非所有的头文件都需要包含保护。实际上,一些头文件(例如assert.h)被设计为可以被多次包含。头文件是否应该被保护是由编写该文件的人所知道的,这就是保护所属的地方。这是一个实现细节,包含头文件的文件不应该根据被包含的文件使用两种不同的语法。我希望这能让它更清晰明了。 - rici

4

-2

简单。可以相同; 但某些编译器处理 #import 的方式不同,例如微软编译器:它将在编译时自动包含指定的文件。


2
请避免在已经有好答案的问题中发布如此糟糕的答案。 - prapin

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