首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么在C/C++/ObjC之外的语言中预处理器的使用不是很普遍?

为什么在C/C++/ObjC之外的语言中预处理器的使用不是很普遍?
EN

Stack Overflow用户
提问于 2009-08-12 21:56:24
回答 12查看 1.8K关注 0票数 11

我做了大约4年的Java和VB.Net程序员,做了大约6个月的C#程序员。我还使用了很多动态语言,比如Perl、Python、PHP和JavaScript。

我从来不需要预处理器。

我的问题是:为什么您在C、C++和Objective-C中看到预处理器的广泛使用,而在Java、C#或Scala语言中却很少(或从未)看到它?

EN

回答 12

Stack Overflow用户

回答已采纳

发布于 2009-08-12 22:19:51

我不知道Objective-C,所以我的答案是比较C和C++中预处理器的用法。

出于几个原因,预处理器最初是C语言所必需的。如果我没记错的话,最初的C没有常量,所以需要#define来避免幻数。在1999年之前,C语言没有内联函数,所以仍然使用#define来创建宏或“伪函数”,以节省函数调用的开销,同时保持代码结构。C也没有运行时或编译时的多态性,所以条件编译需要#ifdef。编译器通常不够智能,无法优化掉无法访问的代码,因此,再次使用#ifdef来插入调试或诊断代码。

在C++中使用预处理器是对C的一种倒退,通常是不受欢迎的。语言特性,如常量、内联函数和模板,可以在C中使用预处理器的大多数情况下使用。

在少数情况下,在C++中使用预处理器是可以接受的,甚至是必要的,包括对头文件的保护,以防止相同的头文件被多次包含,#ifdef __cplusplus对C和C++使用相同的头,__FILE____LINE__用于日志记录,等等。

预处理器也经常用于特定于平台的定义,尽管Stephen Dewhurst的C++ Gotchas建议为特定于平台的定义设置单独的包含目录,并在每个平台的单独构建配置中使用它们。

票数 14
EN

Stack Overflow用户

发布于 2009-08-12 22:15:05

您没有看到Java、C#或Scala中使用的预处理器的原因是这些语言显然没有预处理器。

C预处理器的一个常见用途是帮助提供特定于平台的代码。由于C(我在这里包括C++和Objective-C )是一种需要直接与操作系统交互的低级语言,因此在可移植代码中,必须针对不同的操作系统编译不同的代码部分。您可以在成熟的、高度可移植的代码库(如zlib )中找到这类事情的大量示例。

举个简单的例子,要关闭一个网络套接字,必须这样做(在某种程度上,这当然可以包装在一个函数中,但它必须存在于某个地方):

代码语言:javascript
复制
#ifdef WIN32
    closesocket(s);
#else
    close(s);
#endif

在VM上运行的较新语言不需要不同的特定于平台的代码部分,并且可以针对单个可移植的标准库进行编写。

预处理器还提供了一种用C定义常量的方法,这些常量是由较新语言中的其他更好的语言特性提供的。

在C++的设计和演变中,Bjarne Stroustrup表示,他想要消除对C++中预处理器的依赖,但没有成功。

票数 11
EN

Stack Overflow用户

发布于 2009-08-12 23:21:39

每种语言都需要一种单独编译的机制。理想情况下,该语言将接口与实现区分开来,并且模块仅依赖于它导出的模块的接口。(例如,参见Ada、Clu、Modula等。)

C语言没有用于接口或实现的语言构造。因为不同的.c文件共享接口的单一视图是至关重要的,所以编程规程逐渐发展为将声明(即接口)放在.h文件中,并使用文本包含(#include)共享这些声明/接口。原则上,#define#ifdef可以省去,但#include不能。

现在的语言设计者认识到文本包含不是运行铁路的方法,所以语言倾向于运行到单独编译的接口(Ada,Modula,OCaml),编译器生成的接口(Haskell),或者运行到保证接口一致性的动态系统(Java,Smalltalk)。有了这样的机制,就不需要预处理器了,也有很多理由不需要预处理器(想想源代码分析和调试)。

票数 9
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1268963

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档