代码之家  ›  专栏  ›  技术社区  ›  cdmckay

为什么预处理器的使用在C/C+++Objc以外的语言中较不常见?

  •  10
  • cdmckay  · 技术社区  · 15 年前

    我从事Java和VB .NET程序员已经4年了,C程序员已经有6个月了。我还使用了一些动态语言,如Perl、Python、PHP和JavaScript。

    我从未需要过预处理器。

    我的问题是:为什么你在C、C++和Objy-C中看到预处理器的广泛使用,但是很少使用(或者从来没有)用Java语言、C语言或斯卡拉语言?

    12 回复  |  直到 14 年前
        1
  •  13
  •   Dima    15 年前

    我不知道Objto-C,所以我的答案是对比C和C++中预处理器的使用情况。

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

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

    在C++中使用预处理器是可接受的,甚至是必要的几个情况下,包括头文件的防护,以防止同一个报头被多次包含, #ifdef __cplusplus 为C和C++使用相同的标头,用于日志记录,以及其他一些。

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

        2
  •  10
  •   Greg Hewgill    15 年前

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

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

    #ifdef WIN32
        closesocket(s);
    #else
        close(s);
    #endif
    

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

    预处理器还提供了一种在C中定义常量的方法,这些常量由更新语言中的其他更好的语言功能提供。

    在C++的设计和进化中,Bjarne Stroustrup表示他想删除C++中预处理器的依赖性,但没有成功。

        3
  •  9
  •   Norman Ramsey    15 年前

    每种语言都需要一种机制 单独汇编 . 理想情况下,语言将接口与实现区分开来,并且模块仅依赖于其导出的模块的接口。(请参见,例如ADA、CLU、MODULA等。)

    C没有接口或实现的语言结构。因为不同的.c文件共享接口的单一视图是至关重要的,所以编程规则演变为将声明(即接口)放入.h文件并使用文本包含方式共享这些声明/接口。( #include )在原理上, #define #ifdef 可以免除,但是 包括: 不能。

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

        4
  •  4
  •   Community Egal    7 年前

    因为这些语言的设计和目标不一样。

    C是在预处理器的基础上构建的,作为一个强大的工具,它被用来实现非常基础的东西(比如包含保护),开发人员可以使用它来优化他们的代码,或者选择包括/排除某些代码块以及其他东西。 C++继承了大多数C的成语,宏不再用于速度(因为内联被引入),但它仍然用于大量的事物,参见文章。 What are preprocessor macros good for?

        5
  •  3
  •   rp.    15 年前

    因为戈斯林和海尔斯堡都明白错误的预处理带来的危险和技术债务!

        6
  •  1
  •   Community Egal    7 年前

    C和C++中的预处理器有两个不同的功能

    • 在构建过程中将文件拉到一起-语言 像Java等。有他们自己的机制,比如import来做这件事

    • 执行文本替换-这仍然需要在一定程度上在C,但C++可以做到这一点(在大多数情况下)更好地使用模板

    所以C和C++都需要第一个,但是C++可以把它放在第二个,尽管它在C++中也是有用的。 this question 从今天早些时候开始。

        7
  •  1
  •   Brian Postow    15 年前

    我不同意目前的共识,即CPP在现代语言中是不必要的。我有很多情况下,我有3个稍微不同版本的同一个程序,我想能够作出一系列的改变,为每个版本。使用cpp,我可以将它们全部放在if-else块中,并且可以在编译行定义if。在爪哇中,我需要创建一些静态全局,并在编译时初始化它。我从来没有把它做好。

        8
  •  1
  •   Jim Ferrans    15 年前

    现代语言本身就包含了预处理器!对于C++,预处理只需要用于模块管理和条件包含,例如非常有用。

    我相信它是一个独立的工具,因为编译器不是我们今天所知道的一个工具。我听说非常老的C编译器用于生成文件的令牌,然后在不同的阶段进行其余的编译。我能想到的主要原因是,与我们今天拥有的相比,记忆和其他资源非常稀缺。

        9
  •  1
  •   Porculus    14 年前

    在Java世界中,预处理是非常常见的。它用于补偿语言缺乏足够的内置抽象设施,否则将导致无休止的复制和粘贴样板代码。

    许多人没有意识到这一点是正确的,在Java世界中,它被称为“代码生成”而不是“预处理”,因为“预处理器”听起来像讨厌的老C,而“代码生成”听起来像是一种专业工具,它能有效地提高成熟的企业流程。尽管如此,它仍然是预处理的,即使你必须为一个不兼容的非标准专有工具支付一大笔钱,而不仅仅是使用语言中内置的工具。

        10
  •  0
  •   JDonner    15 年前

    可以肯定的是,现代语言是用C或C++编写的,而在实现本身中也有宏。您需要他们处理操作系统差异,一方面。动态/高级语言包装并隐藏了许多底层需要宏的东西。

    此外,宏有时也用于速度。在动态语言中,速度并没有那么重要。

        11
  •  0
  •   Chris Simmons    15 年前

    您应该更仔细地看一下Perl。Perl支持 source filters ,基本上是用Perl编写的自定义Perl预处理器:)

        12
  •  0
  •   OscarRyz    15 年前

    Java是为了避免一些使C++难以使用的特性而设计的。

    复制或继承大部分来自Java的设计决策。

    高级编程语言避免了这种低级的工件。