2010-03-25 4 views
3

Les faqs C l'expliquent en quelque sorte, here is the link.Comment accéder aux champs de structure par nom lors de l'exécution?

Mais je ne peux pas le comprendre, quelqu'un peut l'expliquer pour moi? Ou me donner un autre moyen?

Merci beaucoup!

+0

Le A est correct, le Q sux cependant. Google "réflexion java", le langage C n'a aucun support pour cela. –

+0

Je connais la réflexion, je l'ai supporté à travers une carte de sauts, java réflexion, ce n'est pas pareil à ma question, mais merci quand même. – drigoSkalWalker

Répondre

5

Je pense que cet exemple rend la réponse claire:

struct test 
{ 
    int b; 
    int a; 
}; 

int main() 
{ 
    test t; 
    test* structp = &t; 

    //Find the byte offset of 'a' within the structure 
    int offsetf = offsetof(test, a); 

    //Set the value of 'a' using pointer arithmetic 
    *(int *)((char *)structp + offsetf) = 5; 

    return 0; 

} 
+0

Je pense qu'il vaut la peine de souligner que le "nom" (a) est ici un symbole de compilation, pas quelque chose qui est trouvé "à l'exécution". Dans le dernier cas, cela devrait être une chaîne, et offsetof() ne fonctionnerait pas. – unwind

1

Vous ne pouvez pas, non sans implémenter une sorte de recherche de nom vous-même.

C ne dispose d'aucune information sur l'heure du nom lorsque le programme est en cours d'exécution.

La prise en charge de ce type de champ struct est généralement compliquée.

1

Si vous avez votre binaire compilé avec les informations de débogage, vous pouvez l'utiliser pour rechercher des noms lors de l'exécution. Par exemple gcc (généralement) produit des informations de débogage au format DWARF et vous pouvez utiliser libdwarf pour le traiter.

En cas de NAIN vous pouvez trouver votre champ DW_TAG_member noeud, DW_AT_data_member_location attribut vous donnera le décalage de champ, même que vous obtenez de offsetof() au moment de la compilation.

0

Conserve la trace des offsets de champs calculés à l'aide de la macro offsetof(). Si structp est un pointeur vers une instance de la structure, et le champ f est un entier ayant compensé offsetf, la valeur de f peut être définie indirectement

*(int *)((char *)structp + offsetf) = value; 
0

Si une structure est définie en utilisant une struct {...}, il est peu probable que il y aura des informations dans le code exécutable liées aux noms des membres. Certaines plates-formes construisent des informations de "débogage" dans des fichiers exécutables générés, et il existe peut-être un moyen par lequel un programme en cours pourrait récupérer ces informations, mais il n'existe pas de façon commune de faire de telles choses.

Cependant, ce que l'on peut faire, c'est d'utiliser des macros pour définir une structure. Par exemple, on pourrait définir:

#define MAKE_ACME_STRUCT \ 
    FIELD(id,int,23) \ 
    X FIELD(name,char30,"Untitled") \ 
    X FIELD(info,int,19) \ 
    // LEAVE THIS COMMENT HERE 

puis invoquer les MAKE_ACME_STRUCT fois macro diverses, avec le champ et les macros X définies de différentes manières, de sorte qu'il élargirait soit à une déclaration de struct, ou une expression d'initialisation pour une instance "par défaut" de cette structure, ou en tant qu'expression d'initialisation pour un tableau d'éléments décrivant les champs struct [par exemple quelque chose comme

STRUCT_INFO acme_struct_info[] = { 
    {"id", STRUCT_INFO_TYPE_int, sizeof(ACME_STRUCT.id), offsetof(ACME_STRUCT.id)} 
    ,{"name", STRUCT_INFO_TYPE_char30, sizeof(ACME_STRUCT.name), offsetof(ACME_STRUCT.name)} 
    ,{"info", STRUCT_INFO_TYPE_int, sizeof(ACME_STRUCT.info), offsetof(ACME_STRUCT.info)} 
    ,{0}}; 

Il serait nécessaire que tous les types utilisés dans le struct ont des noms unique jeton, et que pour chaque nom, un identifiant STRUCT_INFO_TYPE_nameGoesHere être défini qui identifie le type à une bibliothèque d'exécution dans certains forme qu'il comprend.

De telles macros ne sont guère belles, mais elles ont l'avantage de garantir que toutes les choses qu'elles définissent restent synchronisées [par ex. s'assurer que l'ajout ou la suppression d'un élément de acme_struct entraînera son ajout ou son retrait de la liste des membres de la structure stockés dans acme_struct_info].

Questions connexes