簡體   English   中英

字符串化/字符串化名稱修改

[英]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"

這將給出預期的輸出(盡管這兩邊都包含引號)。 linuxunix之所以用1代替,是因為它們已經定義為宏了。 如果您想要不帶任何引號的路徑,您可以預先取消定義unixlinux

#undef unix
#undef linux
#define MY_PATH /path/x86-unix/linux/path

但是當其他庫檢查unixlinux宏時,這可能會導致一些意想不到的問題。 您可以使用#pragma push_macro來防止宏替換(如本答案中所述),但正如您所料,它不是很便攜。

至於 Windows 路徑,它似乎可以在需要時轉義反斜杠:

#define MY_PATH "C:\\Program Files\\Path\\Folder"

這給出了預期的輸出。

為什么會這樣

unixlinux在 UNIX 平台上被定義為 1。

程序/path/x86-unix/linux/pat由標記unixlinux ,因此作為xstr中宏擴展的一部分,這些宏被1替換。

我該如何預防?

#undef linuxunix宏。 或者禁用 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM