繁体   English   中英

是否可以定义另一个预处理器指令?

[英]Is it possible to define another preprocessor directive?

我一直在寻找代码高尔夫,并有一个想法尝试这个代码:

#define D #define添加此行后,一切正常,但我将其扩展为:

#define D #define
D VALUE

在这里我得到了5个编译错误。 如果我把D改成#define一切都很好,有人可以解释,为什么这段代码是非法的?

注意:我使用的是VS2008编译器。

编辑:经过一些答案,我看到我需要给出编译错误列表:

  1. 错误C2121:'#':无效字符:可能是宏扩展的结果
  2. 错误C2146:语法错误:缺少';' 在标识符“VALUE”之前
  3. 错误C4430:缺少类型说明符 - 假定为int。 注意:C ++不支持default-int
  4. 错误C2144:语法错误:'void'前面应加';'
  5. 错误C4430:缺少类型说明符 - 假定为int。 注意:C ++不支持default-int

第一个错误显示D不仅仅是define ,还包括#

C 2011(N1570)6.10.3.4 3:“得到的完全宏替换的预处理标记序列不会被处理为预处理指令,即使它类似于一个......”

C ++ 2010(N3092)16.3.4 [cpp.rescan] 3具有完全相同的文本。

看起来您的预处理器正在进行您想要的替换,但您可能无法获得所需的行为 - 预处理器通常只是单个传递操作。 示例(使用clang,但您应该能够使用适当的VS2008标志重现):

$ cat example.c 
#define D #define
D VALUE
$ cc -P -E example.c 

 #define VALUE

#define VALUE直接进入编译器,编译器不知道如何处理它 - 毕竟它是一个预处理器指令。 Clang的错误,供参考,与您的相似:

$ cc -c example.c 
example.c:2:1: error: expected identifier or '('
D VALUE
^
example.c:1:11: note: expanded from macro 'D'
#define D #define
          ^
1 error generated.

此代码是非法的,因为语言规范说它是非法的。 根据C和C ++预处理器规范,使用预处理器构建的任何代码都不会被解释为另一个预处理器指令。 简而言之,您无法使用预处理器构建预处理程序指令。 期。

(另外,您无法使用预处理器构建注释。)

这是行不通的,因为预处理是在一次通过中执行的。 例如,考虑下一个代码:

#define MYDEFINEWEIRD #define

MYDEFINEWEIRD N 6

int main() {

  return 0;
}

预处理后,您的代码将如下所示:

 #define N 6
int main() {

  return 0;
}

和“#define”不是C或C ++上的有效语法。 此外,由于不会处理生成的预处理程序指令,因此它不会解析代码中对“N”宏的后续引用。

只是为了好玩,您可以使用g ++ / gcc从命令行调用预处理器两次。 考虑下一个代码(define.cpp):

#include <iostream>

#define MYDEFINEWEIRD #define
MYDEFINEWEIRD N 6

using namespace std;

int main() {
  cout << N << endl;
  return 0;
}

然后你可以这样做:

$ g++ -E define.cpp | g++ -o define -x c++ - && ./define

并将输出:

6

预处理器眼中的代码行是预处理器语句(因此没有对它们进行任何替换)或正常的文本语句(并且已经完成替换)。 你不能同时拥有一个,所以一旦你'D'被替换,它只会查看是否还有更多的宏需要替换。 由于没有,它只是在C ++代码中留下'#define',然后C ++编译器在看到它时会出错(因为'#define'不是有效的C ++代码)。

所以更多地表明我的观点,这是预处理器的无效代码:

#define D define
#D value

因为预处理器不对预处理器语句进行任何宏替换,并且“#D”不是可识别的预处理器命令。 和这个:

#define D #define
D value

结果在这个C ++代码中:

#define value

这是无效的,因为预处理器已经完成运行。

查看16 [cpp]段1中的语法, 替换列表pp-tokens组成,其中可包括生产#no-directive ,该指令在同一段的第2段中描述为

非指令不应以列表中出现的任何指令名开头。

也就是说,某种形式

#define NAME # define

恰好是非法的! 另请注意,此上下文中的# 不会将下一个单词转换为字符串: #只会在#函数样式宏中紧跟一个宏参数名后发生。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM