Est-il possible d'accéder à un membre individuel d'une structure ou d'une classe sans connaître le nom de ses variables membres? Je voudrais faire un "offsetof (struct, tyname)" sans avoir le nom de la structure ou le nom de la variable membre codé en dur parmi d'autres choses. merci.Accès aux membres de structures à l'exécution
Répondre
Bien sûr. Si vous avez une structure et que vous connaissez le décalage et le type de la variable membre, vous pouvez y accéder en utilisant des pointeurs.
struct my_struct {
int member1;
char member2;
short member3;
char member4;
}
...
struct my_struct obj;
short member3 = *((short*)((char*)&obj + 5));
qui va obtenir la valeur de member3
, qui est de 5 octets depuis le début de obj
sur un ordinateur x86. Cependant, vous voulez être prudent. Tout d'abord, si la structure change, vos données seront corrompues. Nous jetons partout, donc vous n'obtenez aucun type de sécurité, et le compilateur ne vous avertira pas si quelque chose ne va pas. Vous devrez également vous assurer que le compilateur n'emballe pas la structure pour aligner les variables sur les limites des mots, sinon le décalage changera.
Ce n'est pas une chose agréable à faire, et je l'éviterais si j'étais vous, mais oui, cela peut être fait.
Il est probablement décalé de 6 octets - parce que 'short 'est généralement aligné sur un multiple de 2 octets. Il y a quelques lacunes dans votre structure, et probablement 'sizeof (struct my_struct) == 12'. –
Oui, je viens d'écrire un programme pour le découvrir et on dirait que tu as raison. C'est le danger: il est * habituellement * aligné sur un multiple de 2 octets, mais pas toujours. Salutations pour le rendre limpide. –
Vous devriez lancer 'char *', pas 'void *', puisque 'sizeof (char) == 1'. Le standard C ne définit pas 'sizeof (void *)', donc faire l'arithmétique du pointeur avec 'void *' est un comportement indéfini. En guise d'extension, gcc vous permet de le faire avec 'sizeof (void *) == 1', mais il émet un avertissement quand il le fait. –
Quelque part dans votre code, vous devez référencer le membre de données dans la structure. Cependant, vous pouvez créer une variable qui est un pointeur vers un membre de données struct et à partir de là, vous n'avez plus besoin de le référencer par son nom.
struct foo
{
int member1;
int member2;
};
typedef int (foo::*intMemberOfFoo);
intMemberOfFoo getMember()
{
if (rand() > RAND_MAX/2) return &foo::member1;
else return &foo::member2;
}
foo f;
void do_somthing()
{
intMemberOfFoo m = getMember();
f.*m = 0;
}
C et C++ sont des langages compilés sans fonctionnalités de "réflexion" intégrées. Cela signifie que, indépendamment de ce que vous faites et de la façon dont vous le faites, le chemin commencera toujours d'une manière ou d'une autre à partir d'une valeur codée en dur, que ce soit un nom de membre ou une valeur de décalage à la compilation. Cela signifie que si vous voulez sélectionner un membre struct basé sur une clé d'exécution, vous n'avez pas d'autre choix que de créer manuellement un mappage qui mapperait la valeur de clé à quelque chose qui identifie un membre struct struct.
En C++, afin d'identifier un membre struct au moment de l'exécution, vous pouvez utiliser cette fonctionnalité comme pointeurs vers membres. En C, votre seul choix est d'utiliser une valeur de décalage.
Un autre problème est, bien sûr, de spécifier le type des membres, si vos membres peuvent avoir différents types. Mais vous n'avez fourni aucun détail à ce sujet, et je ne peux donc pas dire si vous avez besoin de le faire ou non.
Nous avons eu un problème similaire il y a quelques années: Une énorme structure d'informations de configuration sur laquelle nous voulions réfléchir. Nous avons donc écrit un script Perl pour trouver le struct, analyser ses membres, et la sortie d'un fichier C++ qui ressemblait à:
struct ConfField
{ const char* name;
int type;
size_t offset;
};
ConfField confFields[] = {
{ "version", eUInt32, 0 },
{ "seqID", eUInt32, 4 },
{ "timestamp", eUInt64, 8 },
// ... lots more ...
{ 0, 0, 0 }
};
Et nous avions alimentons le script avec la sortie de gcc -E
.
De nos jours, je comprends que gccxml peut produire un fichier XML représentant n'importe quelle source C++ que gcc peut compiler, puisqu'il utilise réellement le front-end g ++ pour effectuer l'analyse. Je recommande donc de l'associer à un script d'analyse XML (j'utiliserais Python avec la bibliothèque lxml) pour trouver tout ce que vous avez toujours voulu savoir sur votre source C++.
La réponse technique est 'oui' car C++ est complet à Turing et vous pouvez faire presque n'importe quoi si vous essayez assez fort. La réponse la plus pratique est probablement «non», car il n'y a pas de manière sûre et facile de faire exactement ce que vous voulez.
Je suis d'accord avec GMan. Qu'est-ce que vous essayez exactement de faire qui vous fait penser que vous avez besoin de cette technique?
Eh bien, vous devrez d'abord configurer certaines choses, mais cela peut être fait. L'expansion de la réponse de Samir
struct my_struct {
int member1;
char member2;
short member3;
char member4;
}
vous pouvez créer une table des décalages:
my_struct tmp;
int my_struct_offsets[4]={
0,
(char*)&(tmp.member2)-(char*)&(tmp.member1),
(char*)&(tmp.member3)-(char*)&(tmp.member1),
(char*)&(tmp.member4)-(char*)&(tmp.member1)
}
cela prendra en compte différents alignements sur des systèmes différents
- 1. Accès aux membres de l'application?
- 2. Structures et Unions en C, détermination de la taille et accès aux membres
- 3. Automapper et accès aux variables membres
- 4. Accès aux membres Guid en C#
- 5. Accès aux membres du tableau dans l'assembleur
- 6. Accès aux membres de l'objet et à l'atomicité
- 7. Accès aux événements et aux membres dans la page maître
- 8. Accès aux membres de données de modèle hérités publics
- 9. Accès aux membres de la structure avec un pointeur
- 10. Accès aux membres protégés de sous-classes: gcc vs msvc
- 11. mémoire Allouer aux structures de pointeur à l'intérieur des structures
- 12. Génériques: Accès à de nouveaux membres, membres non cachés
- 13. C#: Accès aux membres d'instance privée hérités par réflexion
- 14. Java: Accès aux membres protégés hérités d'une classe interne
- 15. VB cross-thread Accès aux membres partagés (statiques)
- 16. Accès aux membres non publics d'un objet GridViewCommandEventArgs
- 17. accès aux membres d'un service web dans silverlight
- 18. Accès aux membres protégés du type .NET dans Iron Python
- 19. Accès aux membres de la structure Win32 C/C++ à partir du C#
- 20. Boost Phoenix: Relier à référencer des membres de structures?
- 21. Accès aux membres de la classe avec Invoke à partir d'un thread différent en C#
- 22. liaison aux variables membres
- 23. Structures C++, membres de données publiques et héritage
- 24. MFC: Accès aux vues à partir de l'ordinateur central
- 25. Accès sécurisé et simple aux membres de l'interface explicite en C#
- 26. C# Héritage, accès aux membres enfants avec les fonctions de base?
- 27. Accès aux membres de la propriété de classe dérivée à partir de l'objet de classe de base dans CSharp
- 28. pointeurs aux membres issus de la classe
- 29. Accès aux membres listbox me semble chasser de ma fonction en C#
- 30. classe interne et l'accès aux membres externes
Vous voulez un membre de quelque chose que vous ne savez pas d'un nom que vous ne connaissez pas. Que pensez-vous que vous pouvez faire avec? Dites-nous ce que vous voulez faire, pas ce que vous pensez devoir faire. – GManNickG