Wie kann ich ein String-Literal in der GCC-Befehlszeile definieren?

Lesezeit: 5 Minuten

Richards Benutzeravatar
Richard

In der GCC-Befehlszeile möchte ich eine Zeichenfolge definieren, z -Dname=Mary. Dann möchte ich im Quellcode printf("%s", name); zu drucken Mary.

Wie könnte ich es machen?

  • Ich empfehle Ihnen dringend, Großbuchstaben zu verwenden (-DNAME=\"Mary\")für Token, die Sie auf diese Weise definieren werden, sodass sie wie andere Makros aussehen.

    – JSB

    9. März 2010 um 17:22

  • Das Makro in der Zeichenfolgenfrage: stackoverflow.com/questions/240353/…

    – Ciro Santilli OurBigBook.com

    6. Oktober 2015 um 19:37 Uhr

Zwei Optionen. Maskieren Sie zunächst die Anführungszeichen, damit die Shell sie nicht frisst:

gcc -Dname=\"Mary\"

Oder, wenn Sie -Dname=Mary wirklich wollen, können Sie es stringisieren, obwohl es etwas hackig ist.

#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));
}

Beachten Sie, dass STRINGIZE_VALUE_OF gerne bis zur endgültigen Definition eines Makros ausgewertet wird.

  • Vielen Dank, Arthur. Sie müssen ein Experte in C sein. Weitere Frage: Ich bevorzuge die zweite Option. Wenn ich STRINGIZE_VALUE_OF(name) verwende, wird es in „1“ übersetzt, falls ich gcc -Dname=Mary -DMary habe. Gibt es überhaupt eine Möglichkeit, GCC aufhören zu lassen, Mary zu interpretieren?

    – Richard

    9. März 2010 um 19:24

  • Richard, nach langem Nachdenken glaube ich nicht, dass ich einen Weg finden kann, der im obigen Beispiel funktioniert. Leider haben Sie die Wahl zwischen keiner Erweiterung (z. B. gibt Ihnen „Name“) und einer vollständigen Erweiterung (z. B. Name->Mary->1, wenn Mary als 1 definiert ist). Abhängig von Ihrem genauen Anwendungsfall gibt es möglicherweise Möglichkeiten, dies zu umgehen – wenn Mary beispielsweise zu einem const int statt zu einer define werden kann.

    – Arthur Shipkowski

    10. März 2010 um 2:53

  • Kann jemand eine Begründung dafür nennen, warum Sie solche verschachtelten Stringifizierungsmakros verwenden müssen? Es scheint, als ob das Ergebnis dasselbe sein sollte, aber der Aufruf von STRINGIZE_VALUE_OF() scheint eine Makroerweiterung des Arguments zu erzwingen, während STRINGIZE() dies nicht tut.

    – Ionoklast Brigham

    13. März 2014 um 23:52 Uhr

  • @IonoclastBrigham, habe das bis heute nicht gesehen. Ein Teil davon ist, dass Sie manchmal bloße Wörter in Strings umwandeln möchten – in vielen Fällen wird stringize beispielsweise verwendet, um „asset()“ so zu implementieren, dass es den genauen Ausdruck ausdrucken kann, den Sie haben – in diesem Fall möchten Sie, dass Makros nicht erweitert werden. Sobald Sie erkennen, dass eine Basis-Stringisierung auf diese Weise funktioniert, erzwingt die Verschachtelung eine zweite Runde der Makroerweiterung.

    – Arthur Shipkowski

    9. November 2014 um 23:57 Uhr

  • Die 2. Option ist der richtige Weg, wenn Sie nicht bestehen können [double quote] als Parameter. In meinem Fall ruft Gitlab CI Powershell auf und ruft eine aus Eclipse (Java) kompilierte EXE-Datei auf. Es gibt so viele Interpretationen vor dem Aufruf von gcc, dass es am Ende einfacher ist, damit im C-Code umzugehen.

    – Ofaurax

    7. September 2022 um 8:52

Johns Benutzeravatar
John

Um zu vermeiden, dass die Shell die Anführungszeichen und andere Zeichen „frisst“, können Sie einfache Anführungszeichen wie folgt ausprobieren:

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

Auf diese Weise haben Sie die volle Kontrolle darüber, was definiert wird (Anführungszeichen, Leerzeichen, Sonderzeichen usw.).

Psihodelias Benutzeravatar
Psihodelie

Der portabelste Weg, den ich bisher gefunden habe, war die Verwendung \"Mary\". Es funktioniert nicht nur mit GCC, sondern mit jedem anderen C-Compiler. Zum Beispiel, wenn Sie versuchen, es zu verwenden /Dname=""Mary"" mit einem Microsoft-Compiler wird es jedoch mit einem Fehler abbrechen /Dname=\"Mary\" wird funktionieren.

In Ubuntu habe ich einen Alias ​​verwendet, der CFLAGS definiert, und CFLAGS enthielt ein Makro, das eine Zeichenfolge definiert, und dann verwende ich CFLAGS in einem Makefile. Ich musste die doppelten Anführungszeichen und auch die \-Zeichen maskieren. Es sah ungefähr so ​​aus:

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

Das ist meine Lösung für: -DUSB_PRODUCT=\""Arduino Leonardo\""

Ich habe es in einem Makefile verwendet mit:
GNU Make 3.81 (von GnuWin32)
Und
avr-g++ (AVR_8_bit_GNU_Toolchain_3.5.0_1662) 4.9.2

Die Ergebnisse in einer vorkompilierten Datei (Option -E für g++) sind:
const u8 STRING_PRODUCT[] __attribute__((__progmem__)) = "Arduino Leonardo";

Hosseins Benutzeravatar
Hossein

Hier ist ein einfaches Beispiel:

#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;
}

Wenn ich kompiliere:

$gcc test.c

Ausgang:

__DEBUG__ not defined
10

Wenn ich kompiliere:

$gcc -D __DEBUG__ test.c

Ausgang:

__DEBUG__ defined
30

Benutzeravatar von ewh
ähm

Zu Ihrer Information: Anscheinend können sich in dieser Hinsicht sogar unterschiedliche Versionen derselben Toolchain auf demselben System unterschiedlich verhalten … (Wie in: Es würde.) erscheinen Dies wäre ein Shell-Passing-Problem, aber anscheinend ist es nicht nur auf die Shell beschränkt.

Hier haben wir xc32-gcc 4.8.3 vs. (avr-)gcc 4.7.2 (und mehrere andere) mit demselben Makefile und main.c, mit dem einzigen Unterschied 'make CC=xc32-gcc'usw.

CFLAGS += -D'THING="$(THINGDIR)/thing.h"' wurde am verwendet viele Versionen von gcc (und bash) über mehrere Jahre hinweg.

Um dies mit xc32-gcc kompatibel zu machen (und im Lichte eines anderen Kommentars, der behauptet, dass „\“ portabler ist als „“), musste Folgendes getan werden:

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

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

Dinge machen Wirklich Es ist verwirrend, dies zu entdecken: Anscheinend führt ein nicht in Anführungszeichen gesetztes -D mit einem // zu einem #define mit einem Kommentar am Ende… zB

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

(Danke für die Hilfe von der AntwortS hier übrigens).

1454540cookie-checkWie kann ich ein String-Literal in der GCC-Befehlszeile definieren?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy