Ich suche nach einer Möglichkeit, ein Präprozessor-Token in eine Zeichenfolge zu konvertieren.
Insbesondere habe ich irgendwo:
#define MAX_LEN 16
und ich möchte es verwenden, um ein Überlaufen des Puffers zu verhindern:
char val[MAX_LEN+1]; // room for \0
sscanf(buf, "%"MAX_LEN"s", val);
Ich bin offen für andere Wege, um das Gleiche zu erreichen, aber nur für die Standardbibliothek.
c
c-preprocessor
stringification
davenpcj
quelle
quelle
Antworten:
siehe http://www.decompile.com/cpp/faq/file_and_line_error_string.htm speziell:
#define STRINGIFY(x) #x #define TOSTRING(x) STRINGIFY(x) #define AT __FILE__ ":" TOSTRING(__LINE__)
So kann Ihr Problem gelöst werden
sscanf(buf, "%" TOSTRING(MAX_LEN) "s", val);
quelle
"%" "MAX_LEN" "%"
ein. Wenn Sie buchstäblich ein zweites Makro erhalten, wird der Token- Wert eingefügt, z. B."16"
weil dasTOSTRING
Makro den endgültigen Code entsprechend machtSTRINGIFY(16)
.Ich habe online eine Antwort gefunden.
quelle
Es ist eine Weile her, aber das sollte funktionieren:
sscanf(buf, "%" #MAX_LEN "s", val);
Wenn nicht, muss der Trick "doppelte Erweiterung" durchgeführt werden:
#define STR1(x) #x #define STR(x) STR1(x) sscanf(buf, "%" STR(MAX_LEN) "s", val);
quelle
#
nur Makroargumente stringisiert werden und sich die erste Zeile nicht im Hauptteil eines Makros befindet.Sie sollten den String-Makrotrick mit doppelter Erweiterung verwenden. Oder haben Sie einfach eine
#define MAX_LEN 16 #define MAX_LEN_S "16" char val[MAX_LEN+1]; sscanf(buf, "%"MAX_LEN_S"s", val);
und halten Sie es synchron. (Das ist ein bisschen ärgerlich, aber solange die Definitionen direkt nebeneinander liegen, werden Sie sich wahrscheinlich daran erinnern.)
Eigentlich würde in diesem speziellen Fall nicht
strncpy
ausreichen?strncpy(val, buf, MAX_LEN); val[MAX_LEN] = '\0';
Wenn es jedoch
printf
so wäre, wäre dies einfacher:sprintf(buf, "%.*s", MAX_LEN, val);
quelle
Während einige der oben genannten "funktionieren", würde ich persönlich empfehlen, nur eine einfache String-API anstelle des Drecks zu verwenden, der in libc enthalten ist. Es gibt eine Reihe von portablen APIs, von denen einige auch für eine einfache Integration in Ihr Projekt optimiert sind ... und andere wie ustr haben einen geringen Speicherplatzaufwand und Unterstützung für Stapelvariablen .
quelle
Meine zwei Cent.
#define MAX_LEN 16 #define AUX_VALUE(x) x #define QUOTATION_VALUE() " #define STRINGIFY(x) #x //Ok in all. //#define STRINGIFY(x) QUOTATION_VALUE()AUX_VALUE(x)QUOTATION_VALUE() //Ok only in VC++ std::string str = STRINGIFY(MAX_LEN); const char* str2 = STRINGIFY(MAX_LEN); sscanf(buf, "%" STRINGIFY(MAX_LEN) "s", val);
quelle