Accéder à une variable en C ++ en «assemblant» son nom

Disons que j’ai une variable:

int fish5 = 7; 

Puis-je accéder à fish5 en concaténant les termes “fish” et “5” d’une manière ou d’une autre?

Une solution idéale ressemblerait à ceci:

  printf("I am displaying the number seven: %i", fish + 5); 

Non, pas exactement ce que tu veux. Mais dans votre exemple, vous pouvez utiliser un tableau (ne fonctionne que si vous souhaitez concaténer un nom de variable avec un nombre):

 int fish[6] = {0}; fish[5] = 7; printf("I am displaying the number seven: %i", fish[5]); 

Voir aussi ici pour une référence aux tableaux en C ++.

Une autre solution consisterait plutôt à utiliser std::map , comme l’a souligné Thrustmaster dans les commentaires.

Ensuite, vous pourriez écrire quelque chose comme:

 #include  #include  int main(int argc, char* argv[]){ std::map map; map.insert(std::make_pair("fish5", 7)); printf("I am displaying the number seven: %d", map[std::ssortingng("fish") + std::to_ssortingng(5)]); return 0; } 

Pour plus d’informations sur std::map , voir ici .

Il est impossible de faire passer la solution du moment de la compilation au temps d’exécution, car c ++ est un langage compilé, non interprété. Les noms de variables “perdent leur sens” après la compilation. Ils ne sont qu’un ensemble de symboles avec des adresses. Cela signifie qu’après compilation, demander quelque chose comme fish5 n’a aucun sens.

Pour obtenir ce que vous voulez, vous devez associer le nom à l’object de manière programmée, par exemple en utilisant une carte qui stocke les noms sous forme de clés et les références d’object sous forme de valeurs. Voici comment python le fait et pourquoi, en python, vous pouvez réellement accéder à l’object via son nom à partir du code.

Au cas où quelqu’un se demanderait pourquoi, par exemple, gdb ou crash dumps ont un sens, c’est pour la même raison. Les noms de symbole doivent être enregistrés au moment de la compilation (soit incorporés dans l’exécutable, soit dans un fichier externe), puis un outil externe peut déterminer quel est le nom d’une variable sous une adresse donnée. Mais un exécutable compilé peut très bien fonctionner sans ces informations.

Sinon, vous devez vous rappeler la référence elle-même d’une manière plus pratique, ce qui lui permet d’être calculable. Par exemple, stockez-le dans un tableau et accédez-y sous forme de fish[5] ; bien que, dans cet exemple, il puisse être évalué à la compilation, vous pouvez utiliser la même méthode au moment de l’exécution en utilisant une variable à la place de 5 .

La distinction entre le moment de la compilation et celui de l’exécution est très importante, car vous pouvez réellement faire ce que vous voulez au moment de la compilation avec le pré-processeur, mais uniquement parce que c’est le moment de la compilation.

Vous pouvez utiliser des éléments spécifiques au système d’exploitation, tels que (sous Posix, par exemple, Linux) dlsym (3) pour accéder aux variables via la table des symboles dans l’exécutable ELF (non séparé) au moment de l’exécution.

Donc, déclarez de préférence les variables auxquelles vous souhaitez accéder par leur nom en tant que extern "C" par exemple

  extern "C" int fish17; 

(sinon, prendre en compte le nom spécifique du compilateur en train de changer )

Déclarez également un descripteur de programme:

  void *progdlh; 

initialiser tôt en main

  progdlh = dlopen(NULL, RTLD_NOW|RTLD_GLOBAL); if (!progdlh) { fprintf(stderr, "dlopen failure %s\n", dlerror()); exit(EXIT_FAILURE); } 

ensuite, pour récupérer votre variable par un nom calculé, vous pouvez essayer:

  char nambuf[32]; snprintf (nambuf, sizeof(nambuf), "%s%d", "fish", 17); int *pvar = dlsym(progdlh, nambuf); if (!pvar) { fprintf(stderr, "dlsym %s failure %s\n", nambuf, dlerror()); exit(EXIT_FAILURE); } printf ("variable %s is %d\n", nambuf, *pvar); 

Vous devriez probablement lier votre programme avec l’ -rdynamic (et avec la bibliothèque -ldl )

Ma réponse devrait fonctionner sous Linux.

Vous ne pouvez le faire qu’au moment de la compilation, à l’aide du préprocesseur. Exemple complet:

 #include  #define JOIN(a,b) a##b int main(void) { int fish5 = 5; std::printf("I am displaying the number five: %i", JOIN(fish, 5)); return 0; } 

Cependant, il s’agit ssortingctement du temps de compilation. Si vous essayez JOIN(fish, fish) vous obtenez une error: 'fishfish' undeclared et si vous essayez JOIN("fish", fish) vous obtenez une error: pasting ""fish"" and "fish" does not give a valid preprocessing token .

En C ++, les noms de variables n’existant pas à l’exécution, l’opération ne peut pas être effectuée à l’exécution, à moins que des informations de débogage approfondies ne permettent de rechercher des variables par leur chaîne de nom (comme le fait un débogage). Si l’utilisation de chaînes est une approche valide pour vous, il est préférable d’utiliser explicitement une carte de chaîne en adresse de variable. D’autres réponses montrent comment faire cela déjà, en utilisant std::map .