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