[英]Stringizing / stringify name mangling
I load a path name with cmake我用 cmake 加载了一个路径名
add_definitions(-DMY_PATH =${CMAKE_INSTALL_FULL_DATADIR}/path)
and want to use as a string in my C++ program to load some data.并想在我的 C++ 程序中用作字符串来加载一些数据。 For this the stringification operator # is really handy - I use the macro provided in this answer which is the same as here .
为此,字符串化运算符 # 非常方便 - 我使用此答案中提供的宏,它与 此处相同。 Now when I have "linux" or "unix" in my path, this goes horribly wrong (at least with gcc), as these names are simply replaced by "1":
现在,当我的路径中有“linux”或“unix”时,这会出现严重错误(至少对于 gcc),因为这些名称被简单地替换为“1”:
#include <stdio.h>
#define xstr(a) str(a)
#define str(a) #a
#ifndef MY_PATH
#define MY_PATH /path/x86-unix/linux/path
#endif
int main()
{
char my_path_str[] = xstr(MY_PATH);
printf("my path is %s", my_path_str);
return 0;
}
Can anyone give a hint why is this happening and how I can prevent it?任何人都可以提示为什么会发生这种情况以及我如何防止它? There is a similar question here , but there is no suitable answer to use it with cmake.
还有一个类似的问题在这里,但没有合适的答案与cmake的使用它。
In your case, using quotes around the path that you define will suffice:在您的情况下,在您定义的路径周围使用引号就足够了:
#define MY_PATH "/path/x86-unix/linux/path"
This will give the expected output (though this contains quotes on both the sides).这将给出预期的输出(尽管这两边都包含引号)。 The reason why
linux
and unix
are substituted with 1, is because they are already defined as macros. linux
和unix
之所以用1代替,是因为它们已经定义为宏了。 If you want the path without any quotes, you could undef unix
and linux
beforehand:如果您想要不带任何引号的路径,您可以预先取消定义
unix
和linux
:
#undef unix
#undef linux
#define MY_PATH /path/x86-unix/linux/path
But this might cause some unexpected problems when other libraries check for the unix
or the linux
macro.但是当其他库检查
unix
或linux
宏时,这可能会导致一些意想不到的问题。 You can use #pragma push_macro
to prevent macro substitution (as explained in this answer ), but as you would expect, it is not very portable.您可以使用
#pragma push_macro
来防止宏替换(如本答案中所述),但正如您所料,它不是很便携。
As for Windows paths, it seems to work with escaping the backslash where required:至于 Windows 路径,它似乎可以在需要时转义反斜杠:
#define MY_PATH "C:\\Program Files\\Path\\Folder"
This gives the expected output.这给出了预期的输出。
why is this happening
为什么会这样
Macros unix
and linux
are legacy defined to 1 on UNIX platforms.宏
unix
和linux
在 UNIX 平台上被定义为 1。
Part of the program /path/x86-unix/linux/pat
consists of tokens unix
and linux
, so as part of macro expansion in xstr
these macros are substituted for 1
.程序
/path/x86-unix/linux/pat
由标记unix
和linux
,因此作为xstr
中宏扩展的一部分,这些宏被1
替换。
how I can prevent it?
我该如何预防?
#undef
linux
and unix
macros. #undef
linux
和unix
宏。 Or disable gnu extensions, for example, use c11 standard.或者禁用 gnu 扩展,例如使用 c11 标准。 With GCC compiler on Linux:
在 Linux 上使用 GCC 编译器:
$ gcc -E -dM - </dev/null | grep linux
#define __linux 1
#define __gnu_linux__ 1
#define linux 1 // here it is
#define __linux__ 1
$ gcc -std=c11 -E -dM - </dev/null | grep linux
#define __linux 1
#define __gnu_linux__ 1
#define __linux__ 1
// now there's no #define linux
how I can prevent it?
我该如何预防?
I load a path name with cmake and want to use as a string in my C++ program
我用 cmake 加载了一个路径名,并想在我的 C++ 程序中用作字符串
Adapting example from Example
section fromCMake documentation of configure_file , create a file named my_path.h.in
with content:改编来自configure_file 的 CMake 文档
Example
部分的示例,创建一个名为my_path.h.in
的文件,内容为:
#cmakedefine MY_PATH "@MY_PATH@"
Add the following to your cmake configuration:将以下内容添加到您的 cmake 配置中:
set(MY_PATH "/path/x86-unix/linux/path")
# Generate the file
configure_file(my_path.h.in
${CMAKE_CURRENT_BINARY_DIR}/generated/my_path.h
ESCAPE_QUOTES
@ONLY
)
# add the path to your target
target_include_directories(your_target
PUBLIC_or_PRIVATE
${CMAKE_CURRENT_BINARY_DIR}/generated
)
And use #include <my_path.h>
in your program to get MY_PATH
definitions.并在程序中使用
#include <my_path.h>
来获取MY_PATH
定义。
I see no reason to use a macro - maybe it would be better to do static const char MY_PATH[] = "@MY_PATH@";
我认为没有理由使用宏 - 也许最好做
static const char MY_PATH[] = "@MY_PATH@";
instead.反而。
I load a path name with cmake
我用 cmake 加载了一个路径名
add_definitions(-DMY_PATH =${CMAKE_INSTALL_FULL_DATADIR}/path)
Do not use add_definitions
.不要使用
add_definitions
。 Prefer target_compile_definitions
instead.更喜欢
target_compile_definitions
。 See CMake add_definitions documentations .请参阅CMake add_definitions 文档。
As a crude workaround, you can add quotes, assuming the shell and compiler will properly parse them:作为一个粗略的解决方法,您可以添加引号,假设 shell 和编译器将正确解析它们:
target_compile_definitions(your_target PRIVATE
MY_PATH="${CMAKE_INSTALL_FULL_DATADIR}/path"
)
(Note that quotes in the above are preserved literally and passed to the compiler (or build system). CMake quoting does not work like shell quoting. In CMake language, to quote a word, quotes "
have to be exactly the first and last characters of the word. If one of them is in the middle, they are interpreted literally) (请注意,上面的引号按字面保留并传递给编译器(或构建系统)。CMake 引用不像 shell 引用那样工作。在 CMake 语言中,要引用一个单词,引号
"
必须恰好是第一个和最后一个字符词。如果其中一个在中间,则按字面解释)
However, I think using configure_file
would be preferred, because of ESCAPE_QUOTES
.但是,我认为使用
configure_file
会是首选,因为ESCAPE_QUOTES
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.