如何在GCC命令行中定义字符串文字?

r6hnlfcb  于 2023-05-07  发布在  其他
关注(0)|答案(9)|浏览(215)

在GCC命令行中,我想定义一个字符串,比如-Dname=Mary。然后在源代码中,我希望printf("%s", name);打印Mary
我怎么能这么做呢?

iecba09b

iecba09b1#

两个选择首先,转义引号,这样shell就不会吃掉它们:

gcc -Dname=\"Mary\"

或者,如果你真的想要-Dname=玛丽,你可以把它字符串化,尽管它有点古怪。

#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将很乐意向下计算到宏的最终定义。

a5g8bdjr

a5g8bdjr2#

为了避免shell“吃掉”引号和其他字符,您可以尝试单引号,如下所示:

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

这样,您就可以完全控制所定义的内容(引号、空格、特殊字符等)。

py49o6xq

py49o6xq3#

到目前为止,我发现的最便携的方法是使用\"Mary\"。它不仅适用于GCC,还适用于任何其他C编译器。例如,如果您尝试在Microsoft编译器中使用/Dname='"Mary"',它将停止并显示错误,但/Dname=\"Mary\"将正常工作。

8ftvxx2r

8ftvxx2r4#

在Ubuntu中,我使用了一个定义CFLAGS的别名,CFLAGS包含了一个定义字符串的宏,然后我在Makefile中使用CFLAGS。我必须转义双引号字符和\字符。它看起来像这样:

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

xyhw6mcr5#

这是我的解决方案:**-DUSB_PRODUCT=\""Arduino Leonardo\""**
我在一个makefile中使用了它:
GNU Make 3.81(来自GnuWin 32)
和/或
avr-g++(AVR_8_bit_GNU_Toolchain_3.5.0_1662)4.9.2
预编译文件的结果(g++的-E选项)是:
const u8 STRING_PRODUCT[] __attribute__((__progmem__)) = "Arduino Leonardo";

mkh04yzy

mkh04yzy6#

下面是一个简单的例子:

#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
llycmphe

llycmphe7#

仅供参考:显然,即使是同一系统上同一工具链的不同版本,在这方面也会有不同的表现……(就像,这似乎是一个shell传递问题,但显然它不仅限于shell)。
这里我们有xc 32-gcc 4.8.3与(avr-)gcc 4.7.2(和 * 几个 * 其他)使用相同的makefile和main.c,唯一的区别是'make CC=xc32-gcc'等。
CFLAGS += -D'THING="$(THINGDIR)/thing.h"'已经在 * 许多 * 版本的gcc(和bash)上使用了好几年。
为了使它与xc 32-gcc兼容(并且根据另一条评论声称“比'”更可移植),必须做以下事情:

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

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

让事情变得 * 真的 * 令人困惑的发现:显然,一个未加引号的-D和一个//会导致一个#define * 和一个注解 * 在最后...例如
THINGDIR=/thingDir/ -〉#define /thingDir//thing.h -〉#define /thingDir
(谢谢你的回答,顺便说一句)。

wgx48brx

wgx48brx8#

我刚发现我们的一个应用程序不能在Ubuntu上编译。由于Linux和Windows在通用方法上没有达成一致,我使用了以下方法:

NAME := "Mary"

ifeq ($(SystemRoot),)
    # building on another OS
    CFLAGS_ADD += -Dname=\"Mary\"
else
    # building on Windows
    CFLAGS_ADD += -Dname=\\\"Mary\\\"
endif
lmvvr0a8

lmvvr0a89#

考虑:

{
    "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\""
        }
    ]
}

我在Visual Studio 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上的Visual Studio Code都有效。这里描述的其他方法,如"-Dname=\"SHERAJ\"""-Dname=\\\"SHERAJ\\\""不适合我。
所以答案是"-DSHERAJ"

相关问题