对 C 以外的语言使用 C 预处理器

发布于 2024-07-26 16:32:55 字数 340 浏览 4 评论 0原文

C 预处理器 的 Wikipedia 条目指出:

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

如何才能做到这一点? 有什么例子或技巧吗?

编辑:是的,我最感兴趣的是宏处理。 尽管它可能不可取或不可维护,但了解可能的情况仍然很有用。

The Wikipedia entry for the C Preprocessor states:

The language of preprocessor
directives is agnostic to the grammar
of C, so the C preprocessor can also
be used independently to process other
types of files.

How can this be done? Any examples or techniques?

EDIT: Yes, I'm mostly interested in macro processing. Even though it's probably not advisable or maintainable it would still be useful to know what's possible.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(12

被翻牌 2024-08-02 16:32:56

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

A while ago I did some work on a project that used imake for makefile generation. As I recall, it was basically the c preprocessor syntax to generate the make files.

心凉 2024-08-02 16:32:56

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

The C preprocessor can also be invoked by the Glasgow Haskell Compiler (GHC) prior to compiling Haskell code, by passing the -cpp flag.

毁梦 2024-08-02 16:32:56

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

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

You could implement the C preprocessor in the compiler for another language.

You could use it to preprocess any sort of text file, but there's much better things for that purpose.

深陷 2024-08-02 16:32:56

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

例如,在一个文本文件上:

#define pi 3.141

pi is not an irrational number.

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

3.141不是一个无理数。

Basically what it's saying is that preprocessors have nothing to do with C syntax. They are basically simple parsers that follow a set of rules. So you could use preprocessors kind of like you'd use sed or awk for some silly tasks. Don't ask me why you'd ever want to do it though.

For example, on a text file:

#define pi 3.141

pi is not an irrational number.

Then you run the preprocessor & you'd get.

3.141 is not an irrational number.

故事和酒 2024-08-02 16:32:55

您可以直接调用 CPP:

cpp <file>

而不是通过 gcc 调用它:

gcc -E filename

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

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

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

You can call CPP directly:

cpp <file>

Rather than calling it through gcc:

gcc -E filename

Do note however that, as mentioned in the same Wikipedia article, C preprocessor's language is not really equipped for general-purpose use:

However, since the C preprocessor does not have features of some other
preprocessors, such as recursive macros, selective expansion according
to quoting, string evaluation in conditionals, and Turing
completeness, it is very limited in comparison to a more general macro
processor such as m4.

Have you considered dabbling with a more flexible macro processing language, like the aforementioned m4 for instance?

我很OK 2024-08-02 16:32:55

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

For example, Assembler. While many assemblers have their own way to #include headers and #define macros, it can be useful to use the C preprocessor for this. GNU make, for example, has implicit rules for turning *.S files into *.s files by running the preprocessor ('cpp'), before feeding the *.s file to the GNU assembler ('as').

一曲爱恨情仇 2024-08-02 16:32:55

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

我们在工作中用我们的特定语言做到了这一点。 它有很多优点:

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

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

但是,您还继承了不安全的 C 结构,并且拥有未与您的主语言集成的预处理器考虑一下最小宏并执行以下操作:

a = 2;
b = 3;

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

想想在 min 函数之后 a 和 b 会有什么值?

对于您引入的非类型常量也是如此,

请参阅 更安全的C书了解详细信息。

Yes, it can be done by parsing your own language through the gcc preprocessor (e.g. 'gcc -E').

We have done this on my job with our our, specific language. It has quite some advantages:

  • You can use C's include statements (#include) which is very powerful
  • You can use your #ifdef constructions
  • You can define Constants (#define MAGIC_NUMBER 42) or macro functions (#define min(x,y) ( (x( < (y) ? (x) : (y))

... and the other things in the c processor.

HOWEVER, you also inherit the unsafe C constructions, and having a preprocessor not integrated with your main language is the cause of it. Think about the minimum macro and doing something like :

a = 2;
b = 3;

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

Just think what value a and b will have after the min function?

Same is true about the non-typed constants that you introduce

See the Safer C book for details.

就此别过 2024-08-02 16:32:55

许多 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 编译器,您必须检查手册以了解如何切换到仅预处理模式。

Many C compilers have a flag that tells them to only preprocess. With gcc it's the -E flag. eg:

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

will output:

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

bar foo baz

With other C compilers you'll have to check the manuals to see how to swithc to preprocess-only mode.

挥剑断情 2024-08-02 16:32:55

通常,您可以使用仅进行预处理的选项来调用 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 中的注释,因此您不必为“调试”构建对它们进行预处理。

编辑:既然您询问了宏。 这也很好用,可以用来生成样板代码等。

Usually you can invoke the C compiler with an option to preprocess only (and ignore any #line statements). Take this as a simple example:

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

foo();

We define a PHP source file with preprocess statements. We can then preprocess it (gcc can do this, too):

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

Since DEBUG is not the defined the first echo is stripped. Plus here is that lines beginning with # are comments in PHP so you don't have to preprocess them for a "debug" build.

Edit: Since you asked about macros. This works fine too and could be used to generate boilerplate code etc.

遗忘曾经 2024-08-02 16:32:55

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

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

Using Microsoft's compiler, I think (I just looked it up, haven't tested it) that it's the /P compiler option.

Other compilers presumably have similar options (or, for some compilers the preprocessor might actually be a different executable, which is usually run implicitly by the compiler but which you can also run explicitly separately).

但可醉心 2024-08-02 16:32:55

假设您正在使用 GCC,您可以获取任何纯旧文本文件,无论其内容如何,​​然后运行:

gcc -E filename

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

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

Assuming you're using GCC, You can take any plain old text file, regardless of its contents, and run:

gcc -E filename

Any preprocessor directives in the file will be processed by the preprocessor and GCC will then exit.

The point is that it doesn't matter what the actual content of the text file is, since all the preprocessor cares about is its own directives.

无言温柔 2024-08-02 16:32:55

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

然而,不给它一个是一个有意识的设计决定,所以这样做是非常不符合 Ada 标准的。 我不会建议任何人这样做。

I have heard of people using the C pre-processor on Ada code. Ada has no preprocessor, so you have to do something like that if you want to preprocess your code.

However, it was a concious design decision not to give it one, so doing this is very un-Ada. I wouldn't suggest anyone do this.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文