gpt4 book ai didi

C预处理器: building a path string

转载 作者:太空狗 更新时间:2023-10-29 15:03:48 24 4
gpt4 key购买 nike

给定一个之前定义的宏:

#define FILENAME somefile.h

我想将它与定义该文件(相对)路径的另一个宏字符串连接起来。我目前的做法是这样做:

#define DIRECTORY ../somedir/

#define STRINGIFY_(x) #x
#define FILE2_(dir, file) STRINGIFY_(dir ## file)
#define FILE_(dir, file) FILE2_(dir, file)

#include FILE_(DIRECTORY, FILENAME)

然而,这会导致错误 (GCC4.9):

error: pasting "/" and "file" does not give a valid preprocessing token

DIRECTORY 定义中删除最后一个正斜杠可以消除此错误,但显然不会产生所需的结果。当我尝试以其他方式走私 / 时,会出现类似的错误。例如:

#define FILE2_(dir, file) STRINGIFY_(dir ## / ## file)

出于同样的原因不起作用。

我想知道这里出了什么问题,显然,我想知道如何避免这种情况。

编辑:根据 Columbo 的建议将双下划线更改为单下划线。显然,包含双下划线的标识符保留给实现,无论它们出现在哪里(我的印象是这只适用于 ID 开头的双下划线)。

最佳答案

[cpp.include]/4:

A preprocessing directive of the form

        # include pp-tokens new-line

(that does not match one of the two previous forms) is permitted. The preprocessing tokens after include in the directive are processed just as in normal text (i.e., each identifier currently defined as a macro name is replaced by its replacement list of preprocessing tokens). If the directive resulting after all replacements does not match one of the two previous forms, the behavior is undefined.152


152 Note that adjacent string literals are not concatenated into a single string literal (see the translation phases in 2.2); thus, an expansion that results in two string literals is an invalid directive.

虽然#include MACRO有效,MACRO必须直接扩展为 #include 的有效参数.字符串文字的连接发生在预处理后的两个翻译阶段。

此外,在 ## 的定义中运算符,[cpp.concat]/3:

For both object-like and function-like macro invocations, before the replacement list is reexamined for more macro names to replace, each instance of a ## preprocessing token in the replacement list (not from an argument) is deleted and the preceding preprocessing token is concatenated with the following preprocessing token. [..] If the result is not a valid preprocessing token, the behavior is undefined.

因此 A##B 的结果必须是一个有效的预处理 token 。/是一个自己的预处理标记,目录和文件的名称也是如此。
您不能连接 "abc/xyz" , 自 abc/不是有效的预处理标记 - "abc不是一个预处理标记,而是两个,尽管 "abc"是一个。
另一方面,如果您连接 <abc/xyz> , 然后 /xyz连接,检查,我们又遇到了问题。

因此似乎不可能使用 ## 连接路径.你的方法在我看来也是不可能的。


对于 GCC,这很好:

#define PATH <foo/bar/
#define FILE boo>

#define ARG PATH FILE
#include ARG

works因为 GCC 的预处理器删除了空格(出于某种原因)。不适用于 VC++ 或 Clang,而且也不在标准范围内,因此绝对不推荐。

关于C预处理器: building a path string,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29601786/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com