【发布时间】:2020-03-08 00:11:50
【问题描述】:
当我构建我的 C++ 项目时,编译器会生成这个等效的宏:
#define SOLUTION_DIR "c:\dev\my_project\"
在通常的#defined 宏中,尾随转义的双引号会由于未终止的字符串而触发编译器错误,但编译器可以做任何它想做的事情,并且即使字符串无效,它也可以按字面意思提供给代码。
将宏值扩展为 C 字符串的常用方法:
#define STRINGIZE( x ) #x
#define EXPAND( x ) STRINGIZE( x )
在这种情况下不起作用,因为作为参数传递的未终止字符串。
std::string s = EXPAND( SOLUTION_DIR );
...
error: newline in constant
有没有办法提取这个宏的字符串值并在我的代码中使用它相当于:
std::string str = R"(c:\dev\my_project\)";
其中 R 是此处描述的原始字符前缀 https://en.cppreference.com/w/cpp/language/string_literal
注意事项:
- 我尝试使用 R 前缀重写这些宏以避免转义 最后的引号,但无法获得功能版本。
- 我可以告诉编译器定义 SOLUTION_DIR 字符串而不使用 周围的引号,但我无法避免尾随反斜杠。在 但是这种情况下,由于未知,我会收到其他警告和错误 转义序列 (\d) 和尾随的事实 反斜杠表示宏正在继续 下一行。
更新: 以下是那些认为某事已损坏且需要修复的人的背景。
我使用 Visual Studio 2019 (VS)。在项目属性“C++/Preprocessor/Preprocessor Definitions”中可以定义各种宏,格式如下:
NAME1=VALUE1;NAME2=VALUE2;...
然后在编译时作为
#define NAME1 VALUE1
#define NAME2 VALUE2
VS 为各种目录和其他值(调试/发布、32 位或 64 位等)生成许多预定义的宏(不是 C++,而是构建环境宏)。它们采用 $(Name) 形式并设置为一些字符串值,例如:
$(Configuration) Debug
$(SolutionDir) C:\dev\some_project\
它们用于创建与位置无关的项目设置,例如临时或二进制输出目录,或为正在构建的任何版本的项目(例如 Debug/x64)设置正确的环境。
在我的情况下,我需要直接在我的代码中获取当前解决方案路径,并且使用 $(SolutionDir) VS 宏似乎是最简单的方法。
以下是我在“属性/预处理器/预处理器定义”中定义 SOLUTION_PATH 宏的方式:
SOLUTION_DIR="$(SolutionDir)
翻译成最初描述的编译时宏:
#define SOLUTION_DIR "c:\dev\my_project\"
但是,默认情况下,许多扩展为路径的宏,包括 $(SolutionDir),都包含一个无法删除的尾随反斜杠,因此上面的“损坏”宏。
通常可执行二进制文件不需要也不应该知道任何关于其构建目录的信息,因此与路径相关的宏不一定设计用于定义 C++ 宏,尾随反斜杠不是问题。但我的项目需要这些信息,因为它本身会触发其他依赖于当前环境的构建操作。
所以这不是任何组件的故障,一切都按设计工作,只是碰巧对于我的特定项目,能够以这种方式做事将非常有用,即使它是非标准的。
【问题讨论】:
-
无论生成这个宏的东西都被彻底破坏了。如果文件或目录名称的第一个字符是“n”,这将生成一个包含换行符的字符串文字。不管这里的实际意图是什么,都不可能是正确的。修复真正的问题:是什么进程生成了这个损坏的字符串。
-
无法完成。我需要使用这个字符串。
-
只是好奇,为什么是-1?
-
“正是这个字符串”在 C++ 中没有意义。
-
"编译器生成这个等效的宏" - 我很确定它不会。其他东西正在生成该宏,正如@SamVarshavchik 所说,找到并修复它。坏了。