首页 > 解决方案 > 如何使用尾随反斜杠对字符串进行字符串化

问题描述

当我构建我的 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

笔记:

更新: 这里是那些认为某些东西坏了需要修复的人的背景。

我使用 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++ 宏,尾随反斜杠不是问题。但是我的项目需要这些信息,因为它本身会触发其他依赖于当前环境的构建操作。

所以这不是任何组件的故障,一切都按设计工作,只是碰巧对于我的特定项目,能够以这种方式做事非常有用,即使它是非标准的。

标签: c++stringescaping

解决方案


我能够通过添加尾随“。”来完成这项工作:

SOLUTION_DIR="$(SolutionDir)."

结果是等价的:

#define SOLUTION_DIR "C:\dev\my_project\."

它指向同一个目录,现在编译没有错误。


推荐阅读