Je cherche un moyen de convertir un jeton de préprocesseur en chaîne.
Plus précisément, j'ai quelque part:
#define MAX_LEN 16
et je veux l'utiliser pour éviter le dépassement de tampon:
char val[MAX_LEN+1]; // room for \0
sscanf(buf, "%"MAX_LEN"s", val);
Je suis ouvert à d'autres façons d'accomplir la même chose, mais uniquement à la bibliothèque standard.
voir http://www.decompile.com/cpp/faq/file_and_line_error_string.htm spécifiquement:
#define STRINGIFY(x) #x
#define TOSTRING(x) STRINGIFY(x)
#define AT __FILE__ ":" TOSTRING(__LINE__)
afin que votre problème puisse être résolu en faisant sscanf(buf, "%" TOSTRING(MAX_LEN) "s", val);
J'ai trouvé une réponse en ligne.
#define VERSION_MAJOR 4 #define VERSION_MINOR 47 #define VERSION_STRING "v" #VERSION_MAJOR "." #VERSION_MINOR
Ce qui précède ne fonctionne pas mais, espérons-le, illustre ce que j'aimerais faire, c'est-à-dire que VERSION_STRING devienne "v4.47".
Pour générer la forme numérique appropriée, utilisez quelque chose comme
#define VERSION_MAJOR 4 #define VERSION_MINOR 47 #define STRINGIZE2(s) #s #define STRINGIZE(s) STRINGIZE2(s) #define VERSION_STRING "v" STRINGIZE(VERSION_MAJOR) \ "." STRINGIZE(VERSION_MINOR) #include <stdio.h> int main() { printf ("%s\n", VERSION_STRING); return 0; }
Cela fait un moment, mais cela devrait fonctionner:
sscanf(buf, "%" #MAX_LEN "s", val);
Sinon, il faudra une astuce "double expansion":
#define STR1(x) #x
#define STR(x) STR1(x)
sscanf(buf, "%" STR(MAX_LEN) "s", val);
Vous devez utiliser l'astuce de macro de stringification à double expansion. Ou tout simplement avoir un
#define MAX_LEN 16
#define MAX_LEN_S "16"
char val[MAX_LEN+1];
sscanf(buf, "%"MAX_LEN_S"s", val);
et gardez-le synchronisé. (C'est un peu gênant, mais tant que les définitions sont côte à côte, vous vous en souviendrez probablement.)
En fait, dans ce cas particulier, strncpy
ne suffirait-il pas?
strncpy(val, buf, MAX_LEN);
val[MAX_LEN] = '\0';
Si c'était printf
, ce serait plus simple:
sprintf(buf, "%.*s", MAX_LEN, val);
Bien que certains des "travaux" ci-dessus, personnellement, je recommanderais simplement d'utiliser une API de chaîne simple au lieu de la dreck qui vient dans libc. Il existe un certain nombre d'API portables, dont certaines sont également optimisées pour faciliter leur inclusion dans votre projet ... et d'autres comme str ont une surcharge d'espace minime et prennent en charge les variables de pile.