93 votes

Valeurs par défaut dans un Struct C

J'ai une structure de données comme ceci:

 struct foo {
 int id;
 int route;
 int backup_route;
 int current_route;
}

et une fonction update() qui est utilisé pour demander des modifications.

 mise à jour(42, dont_care, dont_care, new_route);

c'est vraiment long et si j'ajoute quelque chose à la structure que j'ai à ajouter un "dont_care" pour CHAQUE appel à la mise à jour( ... ).

Je pense à propos de la passer d'une structure de la place, mais le remplissage de la struct avec "dont_care' avance est encore plus fastidieux que de simplement l'orthographe dans l'appel de fonction. Puis-je créer la structure quelque part avec les valeurs par défaut de ne s'inquiètent pas et il suffit de régler le champs je me soucie d'après je le déclarer comme une variable locale?

 struct foo bar = { .id = 42, .current_route = new_route };
mise à jour (bar);

Quelle est la façon la plus élégante de passer simplement de l'information, je tiens à exprimer à la fonction de mise à jour?

et je veux que tout le reste par défaut -1 (le code secret pour 'fout')

158voto

hlovdal Points 11039

Alors que les macros et/ou des fonctions (comme l'a déjà suggéré) travailler (et pourrait avoir d'autres effets positifs (c'est à dire de débogage crochets)) ils sont plus complexes que nécessaire; le plus simple et peut-être la plus élégante solution est simplement de définir une constante que vous utilisez pour la variable d'initialisation:

const struct foo FOO_DONT_CARE = { // or maybe FOO_DEFAULT or something
    dont_care, dont_care, dont_care, dont_care
};
...
struct foo bar = FOO_DONT_CARE;
bar.id = 42;
bar.current_route = new_route;
update(&bar);

Ce code a pratiquement pas mentalement généraux de la compréhension de l'indirection et il est très clair que les champs dans la barre d'ensemble explicite tout (en toute sécurité) en ignorant ceux que vous ne définissez pas.

16voto

jpalecek Points 31928

Vous pouvez changer votre valeur spéciale secrète à 0 et exploiter la sémantique de membre de la structure par défaut du C

devra ensuite passe 0 en tant que membres du bar non spécifiés dans l’initialiseur.

Ou vous pouvez créer une macro qui va faire l’initialisation par défaut pour vous :

7voto

Matt J Points 15475

<stdarg.h> vous permet de définir des fonctions variadiques (qui acceptent un nombre indéfini d'arguments, comme printf() ). Je définirais une fonction qui prend un nombre arbitraire de paires d'arguments, une qui spécifie la propriété à mettre à jour et une autre qui spécifie la valeur. Utilisez un enum ou une chaîne pour spécifier le nom de la propriété.

5voto

digijock Points 57

Peut-être envisager d'utiliser un préprocesseur définition de macro à la place:

#define UPDATE_ID(instance, id)  ({ (instance)->id= (id); })
#define UPDATE_ROUTE(instance, route)  ({ (instance)->route = (route); })
#define UPDATE_BACKUP_ROUTE(instance, route)  ({ (instance)->backup_route = (route); })
#define UPDATE_CURRENT_ROUTE(instance, route)  ({ (instance)->current_route = (route); })

Si votre instance de (struct foo) est globale, alors vous n'avez pas besoin du paramètre de cours. Mais je suis en supposant que vous avez probablement plus d'une instance. À l'aide de la ({ ... }) bloc est une distribution GNU-ism qui s'applique à GCC; c'est un gentil (safe) de façon à garder les lignes ensemble comme un bloc. Si plus tard vous avez besoin d'ajouter plus pour les macros, tels que la vérification de validation, vous n'aurez pas à vous soucier de casser des choses comme des if/else et ainsi de suite.

C'est ce que je ferais, en fonction des besoins que vous avez indiqué. Des Situations de ce genre sont l'une des raisons que j'ai commencé à l'aide de python beaucoup; la manipulation des paramètres par défaut et telle, devient beaucoup plus simple qu'elle ne l'est avec C. (je suppose que c'est un python fiche, désolé ;-)

4voto

John Millikin Points 86775

Un modèle utilisé par gobject est une fonction variadique et des valeurs énumérées pour chaque propriété. L'interface ressemble à quelque chose comme:

 update (ID, 1,
        BACKUP_ROUTE, 4,
        -1); /* -1 terminates the parameter list */
 

Écrire une fonction varargs est facile - voir http://www.eskimo.com/~scs/cclass/int/sx11b.html . Il suffit de faire correspondre les paires clé -> valeur et de définir les attributs de structure appropriés.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X