【问题标题】:Can C macros change macro keywordC宏可以更改宏关键字吗
【发布时间】:2016-08-05 08:37:07
【问题描述】:

宏可以在C语言中方便地给关键字起别名,但它也可以用来改变宏关键字,所以代替:

#include <stdlib.h>

#define se if

可以写

#inkludu <stdlib.h>

#difinu se if

换句话说,预处理指令是否可以别名,最好是在代码本身之外,例如使用编译器参数,例如 gcc 的 -D

如下所示的简单测试将失败:

#define difinu define
#difinu valoro 2

int main() {
    int aĵo = valoro;
    return 0;
}

出现以下错误:

 % clang makro.c -o makro
makro.c:2:2: error: invalid preprocessing directive
#difinu valoro 2
 ^
makro.c:5:16: error: use of undeclared identifier 'valoro'
    int aĵo = valoro;
              ^
2 errors generated.

【问题讨论】:

  • 你试过了吗?请选择 C ​​和 C++ 之一,这两种语言不相等,它们的预处理器也不相等。
  • 没有。您不能使用预处理器来更改预处理器和语言语法的工作方式。
  • 好的,我添加了我已经尝试过的文档,并将问题限制在 C 中(尽管我会感兴趣 C++ 解决方案)。
  • 你想通过将整个 C 语言翻译成世界语来完成什么翻转?
  • 好吧,正如下面所建议的那样,拥有一种专用语言作为一个长期项目肯定更有意义,包括自托管等等。尤其是在其设计中可能至少部分依赖于世界语常规语法。只是在路上,我会尽可能多地使用世界语。此外,我的目标是使用完整准确的单词,而不是缩短的对应词和其他非字母标记。现在这可能不是一个主要的共同愿望,但可以让我随心所欲地编写代码。

标签: c macros


【解决方案1】:

没有。宏不会改变预处理器指令的处理方式(但当然可以根据#if 等条件指令进行改变)。特别是以下错误

///WRONG CODE
#define inc include
/// the following directive is not recognized as an include
#inc <stdio.h>

顺便说一句,有

#define se if

确实是一个坏习惯,即使它是可能的。它使您的代码se (x&gt;0) {printf("negative x=%d\n", x);} 更难阅读。

考虑也许使用一些其他预处理器来预处理您的源代码,例如m4GPP。这相当于从其他东西生成您的 C(或 C++)代码。

我的感觉是metaprogramming 通常是个好主意:您编写一些专门的程序,例如发出 C 或 C++ 代码(并相应地改进构建过程,例如your Makefile)。但是您可能会设计一个真正的 C 或 C++ 代码生成器(它可以处理和处理某种AST)。解析器生成器(错误地称为compiler-compilers)如ANTLRbison 就是一个很好的例子。还有Qt has moc

另请参阅thisthat 对相关问题的回答。

在尝试自己的代码生成器(或特定领域的语言实现)之前,不要忘记阅读几本教科书(尤其是与编译器相关的)。

【讨论】:

  • 类似于#define TRUE 0 #define FALSE 1
  • 我不知道 GPP,这似乎很适合我正在做的事情。那只是使用世界语关键字对 C 的翻译,没有语法修改。谢谢你。所以对于这个特定的项目,将“se”作为条件语句是有意义的。
  • 但是这样做确实是个坏主意。您希望 C 代码可供世界各地的其他开发人员阅读。只是将关键字翻译成世界语只是令人困惑,并没有增加任何价值。如果您坚持使用世界语关键字制作编程语言,请设计并实现您自己的此类编程语言(并使其比 C 更好)。
  • 我同意这不是一个很好的自我维持目标。然而,在我看来,制作这种项目是了解哪些词汇可能有用,以及在设计和实现更原始的编程语言中有用的概念的好方法。谢谢你的建议。
  • 那么,你的方法会浪费很多时间。更好地开始设计和实现您的“更接近世界语”的编程语言,并逐步在其中添加功能。阅读我提到的其他答案中给出的参考资料。
【解决方案2】:

在历史记录上,但是请注意,是的,前段时间有编译器可以重新定义宏定义,这一事实的证明是来自 IOCCC 1985 的以下条目,它显然在 Vax 上编译得很好当年的780/4.2BSD:

http://ioccc.org/1985/lycklama/lycklama.c

开头是:

#define o define
#o ___o write
#o ooo (unsigned)

【讨论】:

  • 我喜欢 IOCCC 作为已经成为可能的例子。从来没有这样想过。
  • 这比我们今天定义的术语“C”早。
【解决方案3】:

本地化语言确实存在。 Algol68(在 Linux 下可用)是一种非常古老的语言(1968 年),顺便说一句,它是现有的高级语言之一:

IF x < y THEN x ELSE y FI := 3;
( x < y | x | y ) := 3;
IF x < y THEN sin ELSE cos FI(3.14)

在你的情况下,我会为 .eocpp 和 .eohpp 写一个额外的预处理器,比如 .cpp 和 .hpp。这可以 x 翻译特殊字符,甚至是字典翻译。

【讨论】:

    【解决方案4】:

    “#define”是“编译/编译器的宏替换(文本替换)”预处理器的关键字。考虑c中的代码编译阶段,'预处理器->编译器->汇编器->链接器->加载器'..

    因此,当您编译此代码时,预处理器会尝试搜索不存在的关键字“#difinu”。因此您会从预处理器阶段本身收到错误。

    而且 "#define" 是单个关键字,你怎么能期望预处理器将它视为 "#"+"define" 。例如

    #define game olympic 
    main (){
     int abcgame =10;// will it become "abcolympic" ??
     return;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-04-23
      • 2011-12-19
      • 2017-11-07
      • 1970-01-01
      • 2016-06-21
      • 1970-01-01
      • 2021-04-25
      • 1970-01-01
      相关资源
      最近更新 更多