简体   繁体   English

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

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

I've been looking through code golf and got an idea to try this code: 我一直在寻找代码高尔夫,并有一个想法尝试这个代码:

#define D #define after adding this line, everything worked fine, however I expanded it into this: #define D #define添加此行后,一切正常,但我将其扩展为:

#define D #define
D VALUE

And here I got 5 compilation error. 在这里我得到了5个编译错误。 If I change D into #define everything is fine, can someone explain, why this code is illegal? 如果我把D改成#define一切都很好,有人可以解释,为什么这段代码是非法的?

NOTE: I used VS2008 compiler. 注意:我使用的是VS2008编译器。

EDIT: After some answers I see that I needed to give compilations error list: 编辑:经过一些答案,我看到我需要给出编译错误列表:

  1. error C2121: '#' : invalid character : possibly the result of a macro expansion 错误C2121:'#':无效字符:可能是宏扩展的结果
  2. error C2146: syntax error : missing ';' 错误C2146:语法错误:缺少';' before identifier 'VALUE' 在标识符“VALUE”之前
  3. error C4430: missing type specifier - int assumed. 错误C4430:缺少类型说明符 - 假定为int。 Note: C++ does not support default-int 注意:C ++不支持default-int
  4. error C2144: syntax error : 'void' should be preceded by ';' 错误C2144:语法错误:'void'前面应加';'
  5. error C4430: missing type specifier - int assumed. 错误C4430:缺少类型说明符 - 假定为int。 Note: C++ does not support default-int 注意:C ++不支持default-int

First error shows that D is not just define but also includes # . 第一个错误显示D不仅仅是define ,还包括#

C 2011 (N1570) 6.10.3.4 3: “The resulting completely macro-replaced preprocessing token sequence is not processed as a preprocessing directive even if it resembles one,…” C 2011(N1570)6.10.3.4 3:“得到的完全宏替换的预处理标记序列不会被处理为预处理指令,即使它类似于一个......”

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

It does look like your preprocessor is making the substitution you want, but you likely wouldn't get the behaviour you want - the preprocessor is normally just a single pass operation. 看起来您的预处理器正在进行您想要的替换,但您可能无法获得所需的行为 - 预处理器通常只是单个传递操作。 Example (with clang, but you should be able to reproduce by using the appropriate VS2008 flags): 示例(使用clang,但您应该能够使用适当的VS2008标志重现):

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

 #define VALUE

That #define VALUE is going straight through to the compiler, which won't know what to do with it - it's a preprocessor directive, after all. #define VALUE直接进入编译器,编译器不知道如何处理它 - 毕竟它是一个预处理器指令。 Clang's error, for reference, is similar to yours: 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.

This code is illegal because language specification says it is illegal. 此代码是非法的,因为语言规范说它是非法的。 According to C and C++ preprocessor specification, whatever code you build using preprocessor will never be interpreted as another preprocessor directive. 根据C和C ++预处理器规范,使用预处理器构建的任何代码都不会被解释为另一个预处理器指令。 In short, you cannot build preprocessor directives using preprocessor. 简而言之,您无法使用预处理器构建预处理程序指令。 Period. 期。

(Also, you cannot build comments using preprocessor.) (另外,您无法使用预处理器构建注释。)

That won't work because preprocessing is performed in a single pass. 这是行不通的,因为预处理是在一次通过中执行的。 For example, consider the next code : 例如,考虑下一个代码:

#define MYDEFINEWEIRD #define

MYDEFINEWEIRD N 6

int main() {

  return 0;
}

After preprocessing, your code will looks like : 预处理后,您的代码将如下所示:

 #define N 6
int main() {

  return 0;
}

and "#define" is not a valid syntax on C or C++. 和“#define”不是C或C ++上的有效语法。 Also, since the resulting preprocessor directive is not going to be processed, it won't resolve subsequent references to the "N" macro in your code. 此外,由于不会处理生成的预处理程序指令,因此它不会解析代码中对“N”宏的后续引用。

Just for fun, you can call the preprocesor twice from the command line using g++/gcc. 只是为了好玩,您可以使用g ++ / gcc从命令行调用预处理器两次。 Consider the next code (define.cpp) : 考虑下一个代码(define.cpp):

#include <iostream>

#define MYDEFINEWEIRD #define
MYDEFINEWEIRD N 6

using namespace std;

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

Then you can do: 然后你可以这样做:

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

and will output: 并将输出:

6

Lines of code in the pre-processors eyes are either pre-processor statements (And thus don't have any replacements done on them) or normal text statements (And have replacements done). 预处理器眼中的代码行是预处理器语句(因此没有对它们进行任何替换)或正常的文本语句(并且已经完成替换)。 You can't have one be both, so once you have 'D' be replaced it's only going to look to see if there are any more macros to replace. 你不能同时拥有一个,所以一旦你'D'被替换,它只会查看是否还有更多的宏需要替换。 Since there are none, it just leaves '#define' in the C++ code as it is and then the C++ compiler will error when it sees it (Since '#define' isn't valid C++ code). 由于没有,它只是在C ++代码中留下'#define',然后C ++编译器在看到它时会出错(因为'#define'不是有效的C ++代码)。

So show my point more, this is invalid code for the pre-processor: 所以更多地表明我的观点,这是预处理器的无效代码:

#define D define
#D value

Because the pre-processor doesn't do any macro replacement on pre-processor statements, and "#D" isn't a recognized pre-processor command. 因为预处理器不对预处理器语句进行任何宏替换,并且“#D”不是可识别的预处理器命令。 And this: 和这个:

#define D #define
D value

Results in this C++ code: 结果在这个C ++代码中:

#define value

Which is invalid because the pre-processor is already done being run. 这是无效的,因为预处理器已经完成运行。

Looking at the grammar in 16 [cpp] paragraph 1, a replacement-list consists of pp-tokens which may include the production # no-directive which is described in paragraph 2 of the same paragraph as 查看16 [cpp]段1中的语法, 替换列表pp-tokens组成,其中可包括生产#no-directive ,该指令在同一段的第2段中描述为

A non-directive shall not begin with any of the directive names appearing in the list. 非指令不应以列表中出现的任何指令名开头。

That is, something of the form 也就是说,某种形式

#define NAME # define

happens to be illegal! 恰好是非法的! Also note that the # in this context does not turn the next word into a string: the quoting following a # only happens shen the # is immediately followed by a macro parameter name in a function-style macro. 另请注意,此上下文中的# 不会将下一个单词转换为字符串: #只会在#函数样式宏中紧跟一个宏参数名后发生。

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

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