Existe-t-il un moyen de spécifier des arguments par défaut à une fonction en C ?
+1 créatif ! Elle a ses limites, mais elle apporte aussi des paramètres nommés à la table. Notez que, {}
(initialisateur vide) est une erreur C99.
Existe-t-il un moyen de spécifier des arguments par défaut à une fonction en C ?
Wow, tout le monde est si pessimiste par ici. La réponse est oui.
Ce n'est pas trivial : à la fin, nous aurons la fonction principale, une structure de support, une fonction d'encapsulation, et une macro autour de la fonction wrapper. Dans mon travail, j'ai un ensemble de macros pour automatiser tout cela. Une fois que vous aurez compris le processus, il vous sera facile de faire de même.
J'ai écrit ce sujet ailleurs, voici donc un lien externe détaillé pour compléter le résumé ici : http://modelingwithdata.org/arch/00000022.htm
Nous aimerions tourner
double f(int i, double x)
en une fonction qui prend les valeurs par défaut (i=8, x=3.14). Définissez une structure d'accompagnement :
typedef struct {
int i;
double x;
} f_args;
Renommez votre fonction f_base
et définissez une fonction wrapper qui définit les valeurs par défaut et appelle la base :
double var_f(f_args in){
int i_out = in.i ? in.i : 8;
double x_out = in.x ? in.x : 3.14;
return f_base(i_out, x_out);
}
Ajoutez maintenant une macro, en utilisant les macros variadiques du C. De cette façon, les utilisateurs n'ont pas besoin de savoir qu'ils qu'ils remplissent réellement un f_args
structure et pensent qu'ils font comme d'habitude :
#define f(...) var_f((f_args){__VA_ARGS__});
OK, maintenant tout ce qui suit fonctionnerait :
f(3, 8); //i=3, x=8
f(.i=1, 2.3); //i=1, x=2.3
f(2); //i=2, x=3.14
f(.x=9.2); //i=8, x=9.2
Vérifiez les règles sur la façon dont les initialisateurs composés définissent les valeurs par défaut pour connaître les règles exactes.
Une chose qui ne marchera pas : f(0)
car nous ne pouvons pas faire la différence entre une valeur manquante et zéro. D'après mon expérience, c'est un problème auquel il faut faire attention, mais qui peut être résolu par l'utilisation de la commande le besoin s'en fait sentir - la moitié du temps, votre valeur par défaut est vraiment zéro.
Je me suis donné la peine d'écrire ceci parce que je pense que les arguments nommés et les valeurs par défaut rendent vraiment le codage en C plus facile et plus amusant. Et Le C est génial parce qu'il est si simple et qu'il a suffisamment d'éléments pour rendre tout cela possible.
+1 créatif ! Elle a ses limites, mais elle apporte aussi des paramètres nommés à la table. Notez que, {}
(initialisateur vide) est une erreur C99.
Cependant, voici quelque chose de génial pour vous : La norme permet de spécifier des membres nommés plusieurs fois, les derniers étant prioritaires. Ainsi, pour les paramètres nommés uniquement, vous pouvez résoudre le problème des valeurs par défaut et permettre un appel vide. #define vrange(...) CALL(range,(param){.from=1, .to=100, .step=1, __VA_ARGS__})
J'espère que les erreurs du compilateur sont lisibles, mais c'est une excellente technique ! Cela ressemble presque aux kwargs de Python.
Oui. :-) Mais pas de la manière à laquelle on pourrait s'attendre.
int f1(int arg1, double arg2, char* name, char *opt);
int f2(int arg1, double arg2, char* name)
{
return f1(arg1, arg2, name, "Some option");
}
Malheureusement, le C ne permet pas de surcharger les méthodes et vous vous retrouveriez avec deux fonctions différentes. Pourtant, en appelant f2, vous appelleriez en fait f1 avec une valeur par défaut. Il s'agit d'une solution "Don't Repeat Yourself", qui vous permet d'éviter de copier/coller du code existant.
Pour information, je préfère utiliser le nombre à la fin de la fonction pour indiquer le nombre d'args qu'elle prend. C'est plus facile que d'utiliser n'importe quel nombre arbitraire :)
C'est de loin la meilleure réponse, car elle montre un moyen simple d'atteindre le même objectif. J'ai une fonction qui fait partie d'une API fixe que je ne veux pas modifier, mais j'ai besoin qu'elle prenne un nouveau paramètre. Bien sûr, c'est tellement évident que je ne l'ai pas vu (je suis resté bloqué en pensant au paramètre par défaut !).
Pas vraiment. Le seul moyen serait de écrire une fonction varargs et remplir manuellement les valeurs par défaut pour les arguments que l'appelant ne passe pas.
Je ne le recommande pas, mais je voulais simplement vous faire comprendre que c'est possible.
Cependant, comment voulez-vous vérifier si l'appelant passe l'argument ou non ? Je pense que pour que cela fonctionne, ne faut-il pas que l'appelant vous dise qu'il ne l'a pas passé ? Je pense que cela rend l'approche globale un peu moins utilisable - l'appelant pourrait aussi bien appeler une fonction avec un autre nom.
Nous pouvons créer des fonctions qui utilisent des paramètres nommés (uniquement) pour les valeurs par défaut. Ceci est la suite de la réponse de bk.
#include <stdio.h>
struct range { int from; int to; int step; };
#define range(...) range((struct range){.from=1,.to=10,.step=1, __VA_ARGS__})
/* use parentheses to avoid macro subst */
void (range)(struct range r) {
for (int i = r.from; i <= r.to; i += r.step)
printf("%d ", i);
puts("");
}
int main() {
range();
range(.from=2, .to=4);
range(.step=2);
}
La norme C99 définit que les noms ultérieurs dans l'initialisation remplacent les éléments précédents. Nous pouvons également avoir des paramètres positionnels standard, il suffit de modifier la signature de la macro et de la fonction en conséquence. Les paramètres de valeur par défaut ne peuvent être utilisés que dans le style paramètre nommé.
Sortie du programme :
1 2 3 4 5 6 7 8 9 10
2 3 4
1 3 5 7 9
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.
10 votes
Je veux juste un C légèrement meilleur, pas C++. pensez à C+ . avec une variété de petites améliorations tirées de C++, mais pas le grand bazar. Et, s'il vous plaît, pas de link-loader différent. ça ne devrait être qu'une autre étape de type préprocesseur. standardisé. partout...
0 votes
Related question que je n'ai pas vu dans la barre latérale.
0 votes
Je vous dirais d'arrêter d'être un barbare et d'apprendre à utiliser C++(11, ...) bien - jk ! /Je ne peux pas m'en empêcher, désolé.
0 votes
Duplicata possible de Valeurs par défaut des arguments dans les fonctions C et surcharge des fonctions en C