簡體   English   中英

如何在 gcc 命令行中定義字符串文字?

[英]How to define a string literal in gcc command line?

在 gcc 命令行中,我想定義一個字符串,例如-Dname=Mary ,然后在源代碼中我想要printf("%s", name); 打印Mary
我怎么能做到?

兩種選擇。 首先,對引號進行轉義,這樣 shell 就不會吃掉它們:

gcc -Dname=\"Mary\"

或者,如果你真的想要 -Dname=Mary,你可以將它字符串化,雖然它有點 hacky。

#include <stdio.h>

#define STRINGIZE(x) #x
#define STRINGIZE_VALUE_OF(x) STRINGIZE(x)


int main(int argc, char *argv[])
{
    printf("%s", STRINGIZE_VALUE_OF(name));
}

請注意, STRINGIZE_VALUE_OF 會很高興地評估到宏的最終定義。

為避免外殼“吃掉”引號和其他字符,您可以嘗試單引號,如下所示:

gcc -o test test.cpp -DNAME='"Mary"'

這樣您就可以完全控制定義的內容(引號、空格、特殊字符等)。

到目前為止,我發現的最便攜的方法是使用\\"Mary\\" - 它不僅適用於 gcc,還適用於任何其他 C 編譯器。 例如,如果您嘗試將/Dname='"Mary"'與 Microsoft 編譯器一起使用,它將因錯誤而停止,但/Dname=\\"Mary\\"將起作用。

在 Ubuntu 中,我使用了一個定義 CFLAGS 的別名,而 CFLAGS 包含了一個定義字符串的宏,然后我在 Makefile 中使用了 CFLAGS。 我不得不轉義雙引號字符以及 \\ 字符。 它看起來像這樣:

CFLAGS='" -DMYPATH=\\\"/home/root\\\" "'

這是我的解決方案: -DUSB_PRODUCT=\\""Arduino Leonardo\\""
我在 makefile 中使用它:
GNU Make 3.81(來自 GnuWin32)

avr-g++ (AVR_8_bit_GNU_Toolchain_3.5.0_1662) 4.9.2

預編譯文件(g++ 的 -E 選項)中的結果是:
const u8 STRING_PRODUCT[] __attribute__((__progmem__)) = "Arduino Leonardo";

這是一個簡單的例子:

#include <stdio.h>
#define A B+20 
#define B 10
int main()
{
    #ifdef __DEBUG__
        printf("__DEBUG__ DEFINED\n");
        printf("%d\n",A);
    #else
        printf("__DEBUG__ not defined\n");
        printf("%d\n",B);
    #endif
    return 0;
}

如果我編譯:

$gcc test.c

輸出:

__DEBUG__ not defined
10

如果我編譯:

$gcc -D __DEBUG__ test.c

輸出:

__DEBUG__ defined
30

僅供參考:顯然,即使是同一系統上相同工具鏈的不同版本在這方面也會有所不同......(就像,這似乎是一個外殼傳遞問題,但顯然它不僅限於外殼)。

這里我們有 xc32-gcc 4.8.3 與 (avr-)gcc 4.7.2(以及其他幾個)使用相同的 makefile 和 main.c,唯一的區別是'make CC=xc32-gcc'等。

CFLAGS += -D'THING="$(THINGDIR)/thing.h"'多年來一直在許多版本的 gcc(和 bash)上使用。

為了使其與 xc32-gcc 兼容(並且根據另一條評論聲稱 \\" 比 '" 更便攜),必須執行以下操作:

CFLAGS += -DTHING=\"$(THINGDIR)/thing.h\"

ifeq "$(CC)" "xc32-gcc"
CFLAGS := $(subst \",\\\",$(CFLAGS))
endif

在發現這一點時讓事情變得非常令人困惑:顯然帶有 // 的未加引號的 -D 導致 #define在末尾帶有注釋......例如

THINGDIR=/thingDir/ -> #define /thingDir//thing.h -> #define /thingDir

(感謝這里的答案幫助,順便說一句)。

我剛剛發現我們的一個應用程序無法在 Ubuntu 上編譯。 由於 Linux 和 Windows 在通用方法上沒有達成一致,我使用了這個:

NAME := "Mary"

ifeq ($(SystemRoot),)
    # building on another OS
    CFLAGS_ADD += -Dname=\"Mary\"
else
    # building on Windows
    CFLAGS_ADD += -Dname=\\\"Mary\\\"
endif
{
    "version": "2.0.0",
    "tasks": [
        {
            "type": "cppbuild",
            "label": "C/C++: g++.exe build active file",
            "command": "C:\\Program Files\\mingw-w64\\x86_64-8.1.0-posix-seh-rt_v6-rev0\\mingw64\\bin\\g++.exe",
            "args": [
                "-g",
                "-DSHERAJ",
                "${file}",
                "-o",
                "${fileDirname}\\${fileBasenameNoExtension}.exe"
            ],
            "options": {
                "cwd": "C:\\Program Files\\mingw-w64\\x86_64-8.1.0-posix-seh-rt_v6-rev0\\mingw64\\bin"
            },
            "problemMatcher": [
                "$gcc"
            ],
            "group": {
                "kind": "build",
                "isDefault": true
            },
            "detail": "compiler: \"C:\\Program Files\\mingw-w64\\x86_64-8.1.0-posix-seh-rt_v6-rev0\\mingw64\\bin\\g++.exe\""
        }
    ]
}

我已經在 VS Code 中完成了#define SHERAJ 它非常適合競爭性編程,因為 -

int main() {
    ios_base::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    #ifdef SHERAJ
        freopen("input.txt"  , "r", stdin);
    #endif
    int T;
    cin>>T;
    for(int test_case = 1;test_case<=T;test_case++) {
        cout<<"Hello World"<<endl;
    }
}

它適用於 Mac 和 Windows 上的 VS Code。 此處描述的其他方法如"-Dname=\\"SHERAJ\\"""-Dname=\\\\\\"SHERAJ\\\\\\""對我不起作用。

所以答案是"-DSHERAJ"

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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