Stringifizierung eines Makrowerts

Lesezeit: 3 Minuten

Benutzeravatar von SF
SF.

Ich hatte ein Problem – ich muss einen Makrowert sowohl als Zeichenfolge als auch als Ganzzahl verwenden.

 #define RECORDS_PER_PAGE 10

 /*... */

 #define REQUEST_RECORDS \
      "SELECT Fields FROM Table WHERE Conditions" \
      " OFFSET %d * " #RECORDS_PER_PAGE \
      " LIMIT " #RECORDS_PER_PAGE ";"

 char result_buffer[RECORDS_PER_PAGE][MAX_RECORD_LEN];

 /* ...and some more uses of RECORDS_PER_PAGE, elsewhere... */

Dies schlägt mit einer Meldung über “stray #” fehl, und selbst wenn es funktionieren würde, würde ich wohl die Makronamen als Zeichenfolgen erhalten, nicht die Werte. Natürlich kann ich die Werte der endgültigen Methode zuführen ( "LIMIT %d ", page*RECORDS_PER_PAGE ), aber es ist weder hübsch noch effizient. In Zeiten wie diesen wünschte ich mir, der Präprozessor würde Strings nicht besonders behandeln und ihren Inhalt wie normalen Code verarbeiten. Fürs Erste habe ich es mit verwechselt #define RECORDS_PER_PAGE_TXT "10" aber verständlicherweise bin ich nicht glücklich darüber.

Wie macht man es richtig?

  • Für mich auf gcc korrekt vorverarbeitet.

    – kennytm

    16. April 2010 um 13:29 Uhr

  • Beispiel zum Linux-Kernel: lxr.free-electrons.com/source/include/linux/stringify.h?v=4.7

    – Ciro Santilli OurBigBook.com

    3. November 2016 um 17:10 Uhr

  • Ich würde die nochmal überdenken "%d" dort zugunsten einer Abfragevariablen nur nach allgemeinen Grundsätzen. "%d" Es ist unwahrscheinlich, dass es anfällig für Injektionsangriffe ist, aber es scheint eine schlechte Angewohnheit zu sein, sich darauf einzulassen.

    – Allmächtig

    10. September 2018 um 13:30 Uhr

Das xstr Das unten definierte Makro wird nach der Makroerweiterung stringifiziert.

#define xstr(a) str(a)
#define str(a) #a

#define RECORDS_PER_PAGE 10

#define REQUEST_RECORDS \
    "SELECT Fields FROM Table WHERE Conditions" \
    " OFFSET %d * " xstr(RECORDS_PER_PAGE) \
    " LIMIT " xstr(RECORDS_PER_PAGE) ";"

  • Ist dies eine neuere Anforderung? Ich kann mich nicht erinnern, dass solche Tricks das letzte Mal erforderlich waren, als ich Stringification verwendete …

    – PypeBros

    7. Dezember 2012 um 10:37 Uhr

  • Als weitere Referenz ist eine zusätzliche Beschreibung der Mechanik (und Nuance) der Stringifizierung (GNU CPP) verfügbar unter gcc.gnu.org/onlinedocs/cpp/Stringification.html .

    – hoc_age

    27. Mai 2014 um 16:12 Uhr

  • Aktualisierter GCC-Dokumentlink: gcc.gnu.org/onlinedocs/cpp/Stringizing.html#Stringizing

    – Resonanz

    27. Februar 2017 um 20:17 Uhr

  • Dieses Zitat aus dem Dokument hat es mir erklärt: “There is no way to combine an argument with surrounding text and stringize it all together. Instead, you can write a series of adjacent string constants and stringized arguments.

    – Viktor Sergijenko

    12. Dezember 2017 um 16:17 Uhr

  • @VictorSergienko: Das ist nichts Neues und nichts Schädliches – String-Literal-Verkettung, char* abc = "A" "B" "C"; ist in jeder Hinsicht gleichwertig char* abc = "ABC"; Der Trick hier ist, wie man das besaitete Äquivalent erhält, "B" Anstatt von 'B' oder B.

    – SF.

    9. April 2019 um 12:51 Uhr

#include <stdio.h>

#define RECORDS_PER_PAGE 10

#define TEXTIFY(A) #A

#define _REQUEST_RECORDS(OFFSET, LIMIT)                 \
        "SELECT Fields FROM Table WHERE Conditions"     \
        " OFFSET %d * " TEXTIFY(OFFSET)                 \
        " LIMIT " TEXTIFY(LIMIT) ";"

#define REQUEST_RECORDS _REQUEST_RECORDS(RECORDS_PER_PAGE, RECORDS_PER_PAGE)

int main() {
        printf("%s\n", REQUEST_RECORDS);
        return 0;
}

Ausgänge:

SELECT Fields FROM Table WHERE Conditions OFFSET %d * 10 LIMIT 10;

Beachten Sie die Umleitung zu _REQUEST_RECORDS, um die Argumente auszuwerten, bevor Sie sie in Zeichenfolgen umwandeln.

Benutzeravatar von Scott Wales
Scott Wales

Versuchen Sie, Ihre Anführungszeichen doppelt zu maskieren

#define RECORDS_PER_PAGE 10
#define MAX_RECORD_LEN 10

 /*... */
#define DOUBLEESCAPE(a) #a
#define ESCAPEQUOTE(a) DOUBLEESCAPE(a)
#define REQUEST_RECORDS \
      "SELECT Fields FROM Table WHERE Conditions" \
      " OFFSET %d * " ESCAPEQUOTE(RECORDS_PER_PAGE)       \
      " LIMIT " ESCAPEQUOTE(RECORDS_PER_PAGE) ";"

 char result_buffer[RECORDS_PER_PAGE][MAX_RECORD_LEN];

int main(){
  char * a = REQUEST_RECORDS;
}

kompiliert für mich. Das Token RECORDS_PER_PAGE wird um die erweitert ESCAPEQUOTE Makroaufruf, der dann gesendet wird DOUBLEESCAPE werden zitiert.

  • Aber es ersetzt nicht die richtigen Werte, da der Inhalt von # nicht zuerst ausgewertet wird.

    – Mike Weller

    16. April 2010 um 13:40 Uhr

  • @Mike Habe die doppelte Flucht vergessen

    – Scott Wales

    16. April 2010 um 13:45 Uhr

1409520cookie-checkStringifizierung eines Makrowerts

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

Privacy policy