Mon programme est écrit en C pour Linux et possède de nombreuses fonctions avec différents modèles de valeurs de retour: P>
1) un ou deux renvoi Ma confusion survient sur les trois premières fonctions que les pointeurs de retour retour toujours La première option implique généralement des fonctions qui renvoient une longueur qui peut être positive que positive. P>
La deuxième option est généralement impliquée dans les fonctions de traitement des lignes de commande, mais je ne suis pas sûr qu'il a exactement la correction, peut-être de meilleures valeurs serait sortie_success et exit_failure? P>
La troisième option est destinée aux fonctions qui sont pratiques et naturelles à appeler dans des conditions, et je imite habituellement un type booléen ici, en utilisant Malgré tout cela semblant raisonnablement raisonnable, je trouve toujours des zones où cela n'est pas si clair ou évident quant à quel style à utiliser lorsque je crée la fonction, ou quel style est utilisé lorsque je souhaite l'utiliser. P >
Alors, comment puis-je ajouter de la clarté à mon approche lorsque vous décidez des types de retour ici? p> n code> sur le succès et -1 code> sur une défaillance.
2) Quelques 0 code> sur le succès et -1 code> sur une défaillance.
3) Quelques retours 1 sur le succès et 0 sur une défaillance (je refuse généralement d'un type booléen).
4) Les pointeurs retournent 0 code> sur une défaillance (i généralement refuge avec null code>). p>
0 code> sur une défaillance, c'est facile. P>
int code> valeurs 1 et 0. p>
8 Réponses :
Une condition que je puisse penser à l'endroit où votre méthodologie ci-dessus peut échouer est une fonction pouvant renvoyer n'importe quelle valeur, y compris -1, dites une fonction pour ajouter deux numéros signés. P>
Dans ce cas, les tests pour -1 seront sûrement une mauvaise idée. p>
Dans le cas où quelque chose échoue, je voudrais mieux définir un drapeau de condition d'erreur globale fournie par la norme C sous forme de errno code> et l'utiliser pour gérer l'erreur.
Bien que la bibliothèque standard C ++ fournit des exceptions qui décolle beaucoup de travail pour la manipulation des erreurs. P>
Alors, comment puis-je ajouter de la clarté à mon approche lorsque vous décidez des types de retour ici? p> blockQuote>
Le fait que vous pensiez à cela va un long chemin. Si vous proposez une ou deux règles - ou encore plus si elles ont du sens (vous pourriez avoir besoin de plus d'une règle - comme vous le mentionnez, vous voudrez peut-être gérer des pointeurs retournés différemment plutôt que d'autres choses), je pense que vous serez mieux éteint que beaucoup de magasins. P>
J'aime personnellement avoir 0 retourné à une défaillance du signal et non à zéro pour indiquer le succès, mais je n'ai pas de forte besoin de tenir à cela. Je peux comprendre la philosophie qui voudra peut-être inverser ce sens afin de pouvoir renvoyer différentes raisons de l'échec. P>
La chose la plus importante est de disposer de directives qui sont suivies. Même plus agréable est d'avoir des lignes directrices qui ont une justification documentée (je pense qu'avec les rationnelles, les gens sont plus susceptibles de suivre les directives). Comme je l'ai dit, juste le fait que vous pensiez à ces choses vous met en avant de nombreux autres. P>
Pas une réponse réelle à votre question, mais quelques commentaires aléatoires, vous pourriez trouver intéressant:
Il est normalement évident quand utiliser un cas (1), mais il devient laid lorsque des types non signés sont impliqués - Si vous utilisez C99, il n'y a rien de mal à utiliser i utilise J'essaie d'éviter l'affaire (2); Utilisation de Pour des programmes plus compliqués, il pourrait être logique de mettre en œuvre votre propre schéma de traitement des erreurs; Il existe des implémentations assez avancées à l'aide de retour (taille_t) -1 code> fonctionne toujours, mais ce n'est pas joli li>
_bool code>; imo, c'est beaucoup plus propre que d'utiliser un int code> p> li>
renvoyer null code> au lieu de renvoyer 0 code> dans les contextes de pointeur (préférence péronale), mais je vérifie rarement cela comme je le trouve plus naturel pour simplement traiter le pointeur comme un booléen; Un cas commun ressemblerait à ceci: p>
struct foo *foo = create_foo();
if(!foo) /* handle error */;
EXIT_SUCCESS CODE> et EXIT_FAILURE CODE> Peut être réalisable, mais IMO Cette approche n'a aucun sens si il y a plus de deux résultats possibles et que vous devrez utiliser un Enum Quoi qu'il en soit p> li>
SETJMP () code> / longjmp () code> autour, mais je préfère quelque chose errno code> à différentes variables pour différents types d'erreurs p> li>
ul> p>
Pourquoi n'utilisez-vous pas la méthode utilisée par la bibliothèque standard C? Oh, attends ... p>
Peut-être parce que je suis inconnu avec ça, soin de m'éclairer?
Tim est probablement simplement sarcastique sur le fait que la bibliothèque standard C n'est pas vraiment cohérente sur ce point ... :-)
FTR: Rasmus a raison, j'étais sarcastique. Mais si vous souhaitez une illumination, étudiez les défilements sacrés: Open-std.org/jtc1/sc22/wg14/www/docs/n1336.pdf
pour ne peut pas échouer déterministe. Oui / Non Les réponses à l'aide d'un type de retour plus spécifique (BOOL) peuvent aider à maintenir la cohérence. Aller plus loin pour des interfaces de niveau supérieur, on peut vouloir penser à renvoyer ou à mettre à jour une structure spécifique de messagerie / de détail de résultats spécifique. P>
Ma préférence pour 0 Pour toujours être un succès est basée sur les idées suivantes: p>
zéro permet de classer de base pour organiser des échecs par des valeurs négatives et positives telles que la défaillance totale du succès conditionné. Je ne recommande pas cela généralement comme il a tendance à être un peu trop peu profond pour être utile et pourrait entraîner des hypothèses comportementales dangereuses. P> Li>
Lorsque le succès est nul, on peut créer un tas d'appels orthogonaux et vérifier le succès du groupe dans une seule condition plus tard en comparant le code de retour du groupe. P>
rc = 0; rc + = func1 (); rc + = func2 (); rc + = func3 (); Si (rc == 0) Succès! P> LI>
Plus important encore de zéro de mon expérience semble être une indication cohérente du succès lorsque vous travaillez avec des bibliothèques standard et des systèmes tiers. P> LI> ol>
C'est une question de préférence, mais ce que j'ai remarqué est l'incohérence. Considérez ceci à l'aide d'un compilateur PRE C99
#define SUCCESS 1 #define ERROR 0
Alors, comment puis-je ajouter de la clarté à mon approche lorsque vous décidez des types de retour ici? p> blockQuote>
Choisissez un modèle em> par type de retour et collez-le avec celui-ci, ou vous vous conduirez fou. Modèle votre motif sur les conventions qui ont longtemps été établies pour la plate-forme: p>
Si vous faites beaucoup d'appels système, une fonction de retour entier doit renvoyer
-1 code> sur une défaillance. P> LI>Si vous ne faites pas d'appels de système, vous êtes libre de suivre la convention des structures de contrôle C que non nulle signifie réussir et zéro signifie échec. (Je ne sais pas pourquoi vous n'aimez pas
bool code>.) P> li>Si une fonction renvoie un pointeur, une défaillance doit être indiquée en retournant
null code>. p> li>Si une fonction renvoie un numéro de point flottant, une défaillance doit être indiquée en renvoyant une NAN. P> LI>
Si une fonction renvoie une gamme complète d'entiers signés et non signés, vous ne devez probablement pas coder le succès ou l'échec de la valeur de retour. P> li> ul>
Test des valeurs de retour est un fléau aux programmeurs C. Si l'échec est rare et que vous pouvez écrire un gestionnaire central, envisagez d'utiliser un Package macro d'exception qui peut indiquer des échecs à l'aide de
longjmp code>. p>
Je suis d'accord. Mais les valeurs de retour de test ne sont pas du boisson, c'est un devoir. Imaginez que nous obtenions des valeurs de retour, des exceptions difficiles, des exceptions douces, des sous-classes d'exceptions, des exceptions remontées et lancées - comme dans d'autres langues. Je suis plutôt heureux de ne pas gérer cela.
Une grande partie de la bibliothèque standard C utilise la stratégie pour ne renvoyer que VRAI (ou 1) sur le succès et la fausse (ou 0) sur l'échec et stocker le résultat dans une localisation transmise. Des codes d'erreur plus spécifiques que "il a échoué" sont stockés dans la variable spéciale errno. P>
quelque chose comme ça int ajouter (int * résultat, int A, int b) code> qui stocke A + B en * résultat et renvoie 1 (ou retourne 0 et définit errno sur une valeur appropriée si A + B se trouve être plus gros que Maxint). P>
Pourquoi refusez-vous en utilisant NULL? Ou des types booléens, à cette affaire?
NULL code> est 0, sauf qu'il y a plus d'informations sémantiques connectées ànull code> 0.