Bigcake a écrit
Pour ce qui est du code, on a clairement pas les même habitudes de mise en forme, ce qui me 'choque' le plus :
- Tu mets des '{' et '}' pour des if ou des for qui ne contiennent qu'une seule ligne
exemple : dans interface.c, fonction Game_Menu_Bouton() :
cette fonction est écrite en 8 lignes, elle pourrai être écrite en 3 sans affecter la clarté du code :
if ((mouseposx >= surfposx) && (mouseposy >= surfposy) && (mouseposx <= (surfposx + surfsizex)) && (mouseposy <= (surfposy + surfsizey)))
return 1;
return 0;
Alors là je ne suis pas d'accord avec toi BigCake.
Le fait de mettre des { } même quand il n'y a qu'une seule instruction est une
bonne pratique.
Du reste, en Java, donc la syntaxe en ce qui concerne les crochets est avoisinante, il y a même des règles automatiques pour le vérifier.
Le
rationale est que si un jour, en faisant une maintenance, tu rajoutes une instruction, c'est vite fait d'oublier qu'il n'y avait pas de crochets et donc de produire un code qui ne fait plus du tout ce qu'on veut.
Donc pour expliciter, au contraire il faut toujours écrire :
if ( condition )
{
instruction;
}
Parce que le jour où ça devient :
if ( condition )
{
instruction1;
instruction2;
}
au moins ça fonctionne comme souhaité...
tandis que tu n'as pas mis les crochets, c'est vite fait d'avoir
if ( condition )
instruction1;
instruction2;
qui à l'évidence ne fait pas du tout ce qu'on souhaite...
La seule exception éventuellement est si l'instruction est vraiment courte, mais dans ce cas, et pour qu'il n'y ait pas de confusion possible lors d'un futur ajout, il vaut mieux ne pas faire de retour de ligne, du genre :
if ( flag ) return 0;
Mais cela dit, on peut tout aussi bien écrire
if ( flag ) { return 0; }
je trouve ça personnellement encore plus lisible.
(Bien sûr dans l'exemple simpliste on voit rapidement l'erreur, mais quand on a toute une arborescence de crochets, c'est vite fait de ne pas s’apercevoir qu'il en manque à un niveau).
P.S.: j'ai indenté à la mode "GNU", bien sûr certains préfèrent le K&R d'origine... les goûts et les couleurs sont dans la nature, à vous de choisir votre style et vous y tenir !
Bigcake a écrit- "i++" fait une instruction de plus que "++i" (après sa dépend des optimisations que fait ton compilateur)
Alors là pareil...
-1) je ne recommande pas (sauf exception à commenter !) de faire des optimisations de ce niveau à la place du compilateur... en général ça rend le code bien moins lisible, le boulot du programmeur est de faire un programme qui tient la route, pas d'optimiser ce qui va être généré selon le processeur ciblé.
-2) une instruction de plus... pour quelle cible processeur ?
-3) i++ et ++i ne font pas la même chose... comment peux-tu proposer hors contexte l'un à la place de l'autre !..
Dans certains cas "pointus", par exemple lorsqu'on joue avec les instructions atomiques et les barrières mémoire, on est effectivement obligé d'aider un peu le compilateur. Mais c'est surtout pour qu'il ne fasse pas d'optimisation qui pourraient casser le programme (comme le fait de déplacer des instructions qui n'ont pas l'air reliées). Dans ces cas extrêmes, on peut en arriver à certaines optimisations... mais certainement pas pour un i++ / ++i !..
Exemple (extrait d'un code que j'ai écrit qui gère une file lifo en DCAS -sur i386/amd64):
do
{
old_Head.age = pHead->age;
asm volatile ("" : : : "memory"); // Compile only barrier: age MUST be
// read BEFORE pFirst to protect from ABA
if ( (old_Head.pFirst= pHead->pFirst) == NULL )
break;
new_Head.age = old_Head.age + 1;
new_Head.pFirst= old_Head.pFirst->pNext;
}
#ifdef LIFO_32
while (
! __sync_bool_compare_and_swap (
(__int64_t *)pHead ,
*((__int64_t *)&old_Head),
*((__int64_t *)&new_Head)
)
);
#else
while (
! __sync_bool_compare_and_swap (
(__int128_t *)pHead ,
*((__int128_t *)&old_Head),
*((__int128_t *)&new_Head)
)
);
#endif
Là on est obligé d'aider le compilateur (instruction asm volatile ... = barrière de compilation ). Si on ne le fait pas, comme il voit un test avec un break de la boucle et une instruction avant le test qui réalise une affectation sans rapport avec le test, le compilateur va se dire :
"chouette, je peux optimiser ça !", en effet, si le test fait sortir de la boucle, on n'a pas besoin de l'affectation. Donc tout simplement, le compilateur va placer l'affectation qui est avant le test après le test.
... et là... paf, le programme ne marche plus. En effet, il est vrai que si on sort de la boucle par le break, on a fait l'affectation pour rien... mais si on ne sort pas de la boucle, il est crucial (pour éviter le Syndrome ABA) que la première affectation soit faite AVANT celle faite dans le test.
Mais ce sont des cas extrêmes, et pour cela il vaut mieux commenter (comme c'est fait) pour que lorsqu'on relit plus tard on se rappelle du pourquoi de la chose (ici protection contre le "ABA syndrom", vous pouvez regarder sur Wikipedia, c'est un machin amusant !)