2012-09-20 2 views
0

Dans notre code, nous avons une grande structure de types mixtes, et voulons stocker une structure (const) en double de valeurs par défaut pour ceux-ci. Lorsque l'utilisateur souhaite définir un paramètre par défaut, il serait intéressant de le faire en prenant simplement le décalage d'adresse de l'élément dans la structure, puis d'affecter la valeur avec le même décalage dans les «valeurs par défaut» struct, un peu comme ceci:Est-ce que cela fonctionne avec les pointeurs void *? Si non, comment?

void *setting = &settings->thing; // Points to a setting 
int offset = setting - &settings; 
void *default = &defaults_struct + offset; // Points to the default value 
*setting = *default; // Set setting to default value 

l'idée étant que si Paramètres-> points de chose à un int8, la valeur de int8 est copié de défaut, mais si Paramètres-> other_thing est un int32, la pleine 32- les bits sont copiés.

La question est, est-ce que cela fonctionne avec les pointeurs de vide comme je l'ai décrit ci-dessus? Sinon, y a-t-il un moyen de le faire? Ai-je manqué un meilleur moyen d'y parvenir?

Modifier pour clarifier: Nous voulons définir une valeur unique dans la structure à la valeur correspondante dans la structure "defaults".

+3

Pourquoi ne pas simplement 'settings-> thing = defaults_struct-> thing'? – interjay

+0

Vous ne pouvez pas faire d'arithmétique de pointeur sur les pointeurs vides, et vous ne pouvez pas copier quoi que ce soit à travers cela. Vous devrez utiliser 'char *' et déterminer la longueur appropriée pour copier (et faire la copie vous-même). – Mat

+0

Vous devez utiliser la macro 'offsetof' pour calculer un décalage. –

Répondre

6

Non, cela ne fonctionne pas. Les pointeurs de type void * n'ont pas de taille associée, c'est-à-dire que l'on ne sait pas quel type de données ils pointent. Il s'ensuit que vous ne pouvez pas faire la tâche comme ça non plus.

Vous devriez probablement copier directement les valeurs par défaut, comme suggéré dans un commentaire.

Notez également que default est un mot réservé en C, donc vous ne devriez pas l'utiliser pour une variable.

Si les valeurs par défaut sont visibles globalement, vous pouvez définir une macro pour cacher:

#define INITIALIZE(s, f) s. f = default_struct. f 

L'utilisateur (que je suppose est un développeur) peut maintenant faire:

struct settings s; 

INITIALIZE(s, thing); 

Cela dit , Je voudrais (en tant que développeur) préfèrent quelque chose comme:

struct settings s = get_default_settings(); 

Ceci est plus clair, et moins magique. Bien sûr, il faut probablement plus de temps pour copier tous les champs, mais les paramètres ne sont généralement pas critiques pour la performance.

Notez que la fonction ci-dessus peut-être juste:

struct settings get_default_settings(void) 
{ 
    static const struct settings the_defaults = {/* the default values go here*/}; 

    return the_defaults; 
} 

qui encapsule parfaitement les valeurs par défaut et supprime le global.

+0

Je peux voir que copie la structure ENTIER, je veux juste définir une valeur de la structure tout en laissant le reste seul. –

1

Il n'existe pas d'informations de type/réflexion intégrées pour l'exécution en C. Pour faire ce que vous avez demandé, vous devez connaître la taille réelle du type que vous copiez au moment de l'exécution.

Si vous voulez vraiment faire ce que vous faites, vous devez définir vos propres informations de type d'exécution, généralement en faisant établir chacune une structure propre .. quelque chose comme ...

struct single_setting { 
int stype; 
union { 
    uint8_t s8; 
    uint16_t s16; 
    uint32_t s32; 
    uint64_t s64; 
    struct { 
    char *s; 
    size_t len; 
    } sstr; 
} u_value; 
}; 

Et puis écrire une fonction pour copier et retourner une telle valeur devient assez simple.

Il s'agit d'un certain travail supplémentaire si tout ce que vous voulez est de copier quelques paramètres, mais c'est à peu près ce que font les grands systèmes de configuration.

+0

Merci, ajouter des métadonnées pour chaque paramètre est quelque chose que j'apprécie mais qui ajoute un surcoût juste sur un système embarqué, d'autant plus que le nôtre est déjà établi (base de code équitable qui aurait besoin d'être mise à jour). J'aime le style d'avoir un "type de réglage" struct pour chaque paramètre. –

Questions connexes