将C预处理器用于C以外的语言

时间:2009-07-08 18:37:42

标签: c-preprocessor

C Preprocessor州的维基百科条目:

  

预处理器的语言   指令与语法无关    C ,所以 C 预处理器也可以   独立使用以处理其他   文件类型。

如何做到这一点?任何例子或技术?

编辑:是的,我最感兴趣的是宏观处理。即使它可能不可取或不可维护,但知道什么是可能的仍然是有用的。

12 个答案:

答案 0 :(得分:19)

您可以直接致电CPP:

cpp <file>

而不是通过gcc调用它:

gcc -E filename

请注意,正如同一篇维基百科文章中所提到的,C预处理器的语言并不是真正适用于通用目的:

  

但是,由于C预处理器没有其他功能   预处理器,如递归宏,选择性扩展等   引用,条件中的字符串评估和图灵   完整性,与更一般的宏相比,它是非常有限的   处理器,如m4。

您是否考虑过使用更灵活的宏处理语言,例如前面提到的m4?

答案 1 :(得分:2)

许多C编译器都有一个标志,告诉他们只进行预处理。使用gcc,它是-E标志。例如:

$ gcc -E -                 
#define FOO foo
bar FOO baz

将输出:

# 1 "<stdin>"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "<stdin>"

bar foo baz

使用其他C编译器,您必须查看手册以了解如何切换到仅预处理模式。

答案 2 :(得分:2)

例如,汇编程序。虽然许多汇编器都有自己的#include头和#define宏的方法,但为此使用C预处理器会很有用。例如,GNU make具有隐式规则,用于在将* .s文件提供给GNU汇编程序('as')之前,通过运行预处理程序('cpp')将* .S文件转换为* .s文件。

答案 3 :(得分:2)

是的,可以通过gcc预处理器解析自己的语言(例如'gcc -E')来完成。

我们用我们特定的语言完成了这项工作。它有很多优点:

  • 您可以使用非常强大的C语言包含语句(#include)
  • 您可以使用#ifdef构造
  • 您可以定义常量(#define MAGIC_NUMBER 42)或宏函数(#define min(x,y)((x(&lt;(y)?(x):(y))

......以及c处理器中的其他内容。

但是,您还继承了不安全的C结构,并且没有与主语言集成的预处理器是它的原因。想想最小的宏,并做一些像:

a = 2;
b = 3;

c = min(a--, b--);

想想min函数后a和b的值是多少?

您引入的非类型常量

也是如此

有关详细信息,请参阅Safer C手册。

答案 4 :(得分:1)

通常,您可以使用仅预处理的选项调用C编译器(并忽略任何#line语句)。以此为例:

<?php
function foo()
{
#ifdef DEBUG
    echo "Some debug info.";
#endif
    echo "Foo!";
}

foo();

我们使用预处理语句定义PHP源文件。然后我们可以预处理它(gcc也可以这样做):

cl -nologo -EP foo.php > foo2.php

由于DEBUG未定义,因此第一个echo被删除。另外,以#开头的行是PHP中的注释,因此您不必为“调试”构建预处理它们。

编辑:因为你问过宏。这也很好用,可以用来生成样板代码等。

答案 5 :(得分:1)

使用微软的编译器,我认为(我只是查了一下,还没有测试过它)它是/P compiler option

其他编译器可能有类似的选项(或者,对于某些编译器,预处理器实际上可能是不同的可执行文件,它通常由编译器隐式运行,但您也可以单独显式运行)。

答案 6 :(得分:1)

假设您正在使用GCC,您可以使用任何普通的旧文本文件,无论其内容如何,​​并运行:

gcc -E filename

文件中的任何预处理程序指令都将由预处理程序处理,然后GCC将退出。

关键是文本文件的实际内容并不重要,因为所有预处理器都关心的是它自己的指令。

答案 7 :(得分:1)

我听说有人在Ada代码上使用C预处理器。 Ada has no preprocessor,如果你想预处理你的代码,你必须做类似的事情。

然而,这是一个很难设计的决定,所以这样做非常不是阿达。我不建议任何人这样做。

答案 8 :(得分:1)

前段时间我在一个使用imake生成makefile的项目上做了一些工作。我记得,基本上是生成make文件的c预处理器语法。

答案 9 :(得分:1)

在编译Haskell代码之前,Glasgow Haskell Compiler(GHC)也可以通过传递-cpp标志来调用C预处理器。

答案 10 :(得分:0)

您可以在编译器中为另一种语言实现C预处理器。

您可以使用它来预处理任何类型的文本文件,但为此目的有更好的事情。

答案 11 :(得分:0)

基本上它说的是预处理器与C语法无关。它们基本上是遵循一组规则的简单解析器。因此,您可以使用预处理器,就像您使用sed或awk进行一些愚蠢的任务一样。不要问我为什么你想要这样做。

例如,在文本文件中:

#define pi 3.141

pi is not an irrational number.

然后你运行预处理器&amp;你会得到的。

  

3.141不是无理数。