[英]Stringizing / stringify name mangling
我用 cmake 加載了一個路徑名
add_definitions(-DMY_PATH =${CMAKE_INSTALL_FULL_DATADIR}/path)
並想在我的 C++ 程序中用作字符串來加載一些數據。 為此,字符串化運算符 # 非常方便 - 我使用此答案中提供的宏,它與 此處相同。 現在,當我的路徑中有“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;
}
任何人都可以提示為什么會發生這種情況以及我如何防止它? 還有一個類似的問題在這里,但沒有合適的答案與cmake的使用它。
在您的情況下,在您定義的路徑周圍使用引號就足夠了:
#define MY_PATH "/path/x86-unix/linux/path"
這將給出預期的輸出(盡管這兩邊都包含引號)。 linux
和unix
之所以用1代替,是因為它們已經定義為宏了。 如果您想要不帶任何引號的路徑,您可以預先取消定義unix
和linux
:
#undef unix
#undef linux
#define MY_PATH /path/x86-unix/linux/path
但是當其他庫檢查unix
或linux
宏時,這可能會導致一些意想不到的問題。 您可以使用#pragma push_macro
來防止宏替換(如本答案中所述),但正如您所料,它不是很便攜。
至於 Windows 路徑,它似乎可以在需要時轉義反斜杠:
#define MY_PATH "C:\\Program Files\\Path\\Folder"
這給出了預期的輸出。
為什么會這樣
宏unix
和linux
在 UNIX 平台上被定義為 1。
程序/path/x86-unix/linux/pat
由標記unix
和linux
,因此作為xstr
中宏擴展的一部分,這些宏被1
替換。
我該如何預防?
#undef
linux
和unix
宏。 或者禁用 gnu 擴展,例如使用 c11 標准。 在 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
我該如何預防?
我用 cmake 加載了一個路徑名,並想在我的 C++ 程序中用作字符串
改編來自configure_file 的 CMake 文檔Example
部分的示例,創建一個名為my_path.h.in
的文件,內容為:
#cmakedefine MY_PATH "@MY_PATH@"
將以下內容添加到您的 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
)
並在程序中使用#include <my_path.h>
來獲取MY_PATH
定義。
我認為沒有理由使用宏 - 也許最好做static const char MY_PATH[] = "@MY_PATH@";
反而。
我用 cmake 加載了一個路徑名
add_definitions(-DMY_PATH =${CMAKE_INSTALL_FULL_DATADIR}/path)
不要使用add_definitions
。 更喜歡target_compile_definitions
。 請參閱CMake add_definitions 文檔。
作為一個粗略的解決方法,您可以添加引號,假設 shell 和編譯器將正確解析它們:
target_compile_definitions(your_target PRIVATE
MY_PATH="${CMAKE_INSTALL_FULL_DATADIR}/path"
)
(請注意,上面的引號按字面保留並傳遞給編譯器(或構建系統)。CMake 引用不像 shell 引用那樣工作。在 CMake 語言中,要引用一個單詞,引號"
必須恰好是第一個和最后一個字符詞。如果其中一個在中間,則按字面解釋)
但是,我認為使用configure_file
會是首選,因為ESCAPE_QUOTES
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.