【问题标题】:How to define a string literal in gcc command line?如何在 gcc 命令行中定义字符串文字?
【发布时间】:2011-01-25 12:59:45
【问题描述】:

在gcc命令行中,我想定义一个字符串如-Dname=Mary,然后在源代码中我要printf("%s", name);打印Mary
我该怎么做?

【问题讨论】:

  • 我强烈建议您使用全大写 (-DNAME=\"Mary\") 来表示您要以这种方式定义的标记,以便它们看起来像其他宏。
  • 字符串问题中的宏:stackoverflow.com/questions/240353/…

标签: c++ c gcc command-line macros


【解决方案1】:

两个选项。首先,转义引号,这样 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 会很高兴地评估为宏的最终定义。

【讨论】:

  • 非常感谢亚瑟。您必须是 C 方面的专家。进一步的问题:我更喜欢第二种选择。当我使用 STRINGIZE_VALUE_OF(name) 时,它会将其转换为“1”,如果我有 gcc -Dname=Mary -DMary。无论如何让 gcc 停止解释 Mary
  • Richard,经过多次审查,我认为我无法想出适用于上述示例的方法。不幸的是,您的选择是无扩展(例如,给您“姓名”)和完全扩展(例如,如果 Mary 被定义为 1,则 name->Mary->1)。根据您的具体用例,可能有一些方法可以解决这个问题——例如,如果 Mary 可以成为 const int 而不是定义。
  • 谁能解释一下为什么需要使用这样的嵌套字符串化宏?看起来结果应该是一样的,但是调用 STRINGIZE_VALUE_OF() 似乎会强制参数的宏扩展,而 STRINGIZE() 不会。
  • @IonoclastBrigham,直到今天才看到这个。部分原因是有时您希望对裸字进行字符串化——例如,在许多情况下,stringize 用于实现 assert() 以便它可以打印出您拥有的确切表达式——在这种情况下,您希望宏未扩展。一旦你意识到基本字符串化是这样工作的,嵌套就会强制进行第二轮宏扩展。
【解决方案2】:

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

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

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

【讨论】:

    【解决方案3】:

    到目前为止,我发现的最可移植的方法是使用\"Mary\" - 它不仅适用于 gcc,而且适用于任何其他 C 编译器。例如,如果您尝试将 /Dname='"Mary"' 与 Microsoft 编译器一起使用,它将因错误而停止,但 /Dname=\"Mary\" 将起作用。

    【讨论】:

      【解决方案4】:

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

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

      【讨论】:

      • 有时,单引号和单引号都不起作用,但这样做了。其他时候,它没有。我认为区别在于标志是否全部放在引号中:1) DEFINES=-DLOGPATH=\"./logfile\" CFLAGS = -v $(DEFINES)....2) DEFINES=-DLOGPATH=\\\"./logfile\\\" CFLAGS = "-v $(DEFINES)...." 使用 -v 编译器选项有助于查看预处理器在做什么。
      【解决方案5】:

      仅供参考:显然,即使是同一系统上同一工具链的不同版本,在这方面的行为也会有所不同…… (如,似乎这将是一个外壳传递问题,但显然它不仅限于外壳)。

      这里我们有 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

      (感谢您在此处回答s的帮助,顺便说一句)。

      【讨论】:

        【解决方案6】:

        这是我的解决方案:<strong>-DUSB_PRODUCT=\""Arduino Leonardo\""</strong>
        我在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";

        【讨论】:

          【解决方案7】:

          这是一个简单的例子:

          #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
          

          【讨论】:

          • 这是一个像布尔值一样使用的定义的好例子。然而,OP 询问了哪些字符串定义更棘手。
          【解决方案8】:

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

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

          【讨论】:

            【解决方案9】:
            {
                "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 SHERAJhere。它非常适合竞争性编程,因为 -

            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"

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2011-07-02
              • 1970-01-01
              • 2011-08-16
              • 1970-01-01
              • 2012-01-31
              • 2010-11-21
              • 1970-01-01
              • 2019-08-02
              相关资源
              最近更新 更多