C Language
Idiomes de programmation C courants et pratiques de développeur
Recherche…
Comparer littéral et variable
Supposons que vous comparez une valeur avec une variable
if ( i == 2) //Bad-way
{
doSomething;
}
Supposons maintenant que vous avez trompés ==
avec =
. Ensuite, il vous faudra du temps pour le comprendre.
if( 2 == i) //Good-way
{
doSomething;
}
Ensuite, si un signe égal est accidentellement omis, le compilateur se plaindra d'une «tentative d'affectation à un littéral». Cela ne vous protégera pas lorsque vous comparez deux variables, mais chaque petite aide est utile.
Voir ici pour plus d'informations.
Ne laissez pas la liste des paramètres d'une fonction vierge - utilisez void
Supposons que vous créez une fonction qui ne nécessite aucun argument lors de son appel et que vous êtes confronté au dilemme de savoir comment définir la liste de paramètres dans le prototype de fonction et la définition de fonction.
Vous avez le choix entre conserver la liste de paramètres vide pour le prototype et la définition. Ils ressemblent donc à la déclaration d'appel de fonction dont vous aurez besoin.
Vous lisez quelque part que l'une des utilisations du mot-clé vide (il y en a peu), est de définir la liste de paramètres des fonctions qui n'acceptent aucun argument dans leur appel. Donc, c'est aussi un choix.
Alors, quel est le bon choix?
REPONSE: en utilisant le mot-clé void
CONSEILS GÉNÉRAUX: Si une langue fournit certaines fonctionnalités à utiliser dans un but spécial, il est préférable de les utiliser dans votre code. Par exemple, utiliser enum
s au lieu de macros #define
(pour un autre exemple).
C11, section 6.7.6.3 "Déclarateurs de fonctions", paragraphe 10:
Le cas particulier d'un paramètre sans nom de type void comme seul élément de la liste spécifie que la fonction n'a pas de paramètre.
Le paragraphe 14 de cette même section montre la seule différence:
… Une liste vide dans un déclarant de fonction qui fait partie d'une définition de cette fonction spécifie que la fonction n'a pas de paramètre. La liste vide dans un déclarant de fonction qui ne fait pas partie d'une définition de cette fonction spécifie qu'aucune information sur le nombre ou les types de paramètres n'est fournie.
Une explication simplifiée fournie par K & R (pages 72-73) pour les éléments ci-dessus:
En outre, si une déclaration de fonction n'inclut pas d'arguments, comme dans
double atof();
cela signifie aussi que rien ne doit être supposé sur les arguments deatof
; tout contrôle des paramètres est désactivé. Cette signification particulière de la liste d'arguments vide est destinée à permettre aux programmes C plus anciens de compiler avec de nouveaux compilateurs. Mais c'est une mauvaise idée de l'utiliser avec de nouveaux programmes. Si la fonction prend des arguments, déclarez-les; s'il ne prend aucun argument, utilisez levoid
.
Voici comment votre prototype de fonction devrait ressembler:
int foo(void);
Et voici comment la définition de la fonction devrait être:
int foo(void)
{
...
<statements>
...
return 1;
}
Un avantage d'utiliser ce qui précède, plus int foo()
type de déclaration (ie. Sans utiliser le mot - clé void), est que le compilateur peut détecter l'erreur si vous appelez votre fonction à l' aide d' une déclaration erronée comme foo(42)
. Ce type d'instruction d'appel de fonction ne provoquerait aucune erreur si vous laissez la liste de paramètres vide. L'erreur passerait silencieusement, non détectée et le code s'exécuterait toujours.
Cela signifie également que vous devez définir la fonction main()
comme ceci:
int main(void)
{
...
<statements>
...
return 0;
}
Notez que même si une fonction définie avec une liste de paramètres vide ne prend aucun argument, elle ne fournit pas de prototype pour la fonction. Le compilateur ne se plaindra donc pas si la fonction est appelée ultérieurement avec des arguments. Par exemple:
#include <stdio.h>
static void parameterless()
{
printf("%s called\n", __func__);
}
int main(void)
{
parameterless(3, "arguments", "provided");
return 0;
}
Si ce code est enregistré dans le fichier proto79.c
, il peut être compilé sous Unix avec GCC (version 7.1.0 sur macOS Sierra 10.12.5 utilisée pour la démonstration) comme ceci:
$ gcc -O3 -g -std=c11 -Wall -Wextra -Werror -Wmissing-prototypes -pedantic proto79.c -o proto79
$
Si vous compilez avec des options plus strictes, vous obtenez des erreurs:
$ gcc -O3 -g -std=c11 -Wall -Wextra -Werror -Wmissing-prototypes -Wstrict-prototypes -Wold-style-definition -pedantic proto79.c -o proto79
proto79.c:3:13: error: function declaration isn’t a prototype [-Werror=strict-prototypes]
static void parameterless()
^~~~~~~~~~~~~
proto79.c: In function ‘parameterless’:
proto79.c:3:13: error: old-style function definition [-Werror=old-style-definition]
cc1: all warnings being treated as errors
$
Si vous donnez à la fonction le prototype formel static void parameterless(void)
, la compilation donne des erreurs:
$ gcc -O3 -g -std=c11 -Wall -Wextra -Werror -Wmissing-prototypes -Wstrict-prototypes -Wold-style-definition -pedantic proto79.c -o proto79
proto79.c: In function ‘main’:
proto79.c:10:5: error: too many arguments to function ‘parameterless’
parameterless(3, "arguments", "provided");
^~~~~~~~~~~~~
proto79.c:3:13: note: declared here
static void parameterless(void)
^~~~~~~~~~~~~
$
Moral - assurez-vous toujours d'avoir des prototypes et assurez-vous que votre compilateur vous indique quand vous n'obéissez pas aux règles.