on m’a (moktar pour ne pas le citer :pleure: ) souvent pauser une question sur un petit problem de C :
Quel doit etre le resultat du code suivant :
if( C>C++ )
printf("C > C++
") ;
doit il afficher ou pas ?
Comme j’aime pas qu’on m’escagasse (et ce a plusieur reprise, n’s’pas m’sieur moktar :P), j’ai donc degainer ma panoplie de compilo c : visualC ^, CodeWarrior 7, djgpp gcc, et cygwin gcc.
et je leur est soumis le programme suivant :
[b]
int main(int argc, char* argv[])
{
int C = 0;
if( C>C++ )
printf("C > C++
") ;
return 0;
}
[/b]
resultat :
VC 6 : n’affiche jamais la chaine.
CW7 : affiche toujours la chaine.
djgpp gcc : affiche toujours la chaine.
cygwin gcc : affiche toujours la chaine.
donc l’idee serait que, d’apres 75% des compilos C++ est evaluer avant d’effectuer la comparaison, ce qui est etonnant car mettre « ++ » apres C signifie au compilateur : resout d’abord l’expression, puit increment C de 1.
mais alors ? pourquoi ?
hey bien parce que d’apres le standard ANSI, et la plus part des commentateurs et autres gourou : une expression contenant en meme temps C et C++ tel que : C>C++, C * C++ et autres est consideree comme non specifie voir non definie. Donc personne ne sait, donc chaque compilateur a le droit de faire ce qu’il veux.
(je tiens a signaler d’ailleurs que pclint (precompilateur pour programmeur pointilleux) couine comme un goret a la simple vue de la ligne en question… )
(et que CodeWarrior n’optimize pas tres bien le code en question vu qu’il effectue le test meme quand il sait que rien ne va changer…)
voir http://www.eskimo.com/~scs/C-faq/q3.1.html
si joins mes notes et les resultat en assenbleur x86 compilo par compilo (sans alt+255, parce que j’ai la fleme )
Note :
- quand j’ecris « C » je veux dire dans la memoire
- quand j’ecris « &C » je veux dire l’adresse en memoire de C
- le plus gros du code assembleur est supprimer pour garder la partie interessante.
VisualC 6:
toujours faux.
debug :
mov eax,dword ptr [ebp-4] ; eax = C
mov ecx,dword ptr [ebp-4] ; ecx = C
mov edx,dword ptr [ebp-4] ; edx = C
add edx,1 ; edx++ → edx = c+1
mov dword ptr [ebp-4],edx ; C = edx
cmp eax,ecx ; Compare eax et ecx
release :
comme le compilo considere le test comme toujours faux : il sort sans
effectuer le test en question.
CodeWarrior 7:
toujours vrais.
debug:
mov edx,dword ptr [ebp-4] ; edx = C
inc dword ptr [ebp-4] ; C++
cmp dword ptr [ebp-4],edx ; Compare edx et C
release:
xor ebx,ebx ; ebx = 0
[…]
mov eax,ebx ; eax = ebx
inc ebx ; ebx++ → ebx = 1
cmp ebx,eax ; Compare eax et ebx.
djgpp gcc 3.1:
toujours vrais
debug :
mov edx, DWORD PTR [ebp-4] ; edx = C
lea eax, [ebp-4] ; eax = &C
inc DWORD PTR [eax] ; C++
cmp edx, DWORD PTR [ebp-4] ; Compare C et edx
release :
comme le compilo considere le test comme toujours vrais : il sort sans
effectuer le test en question et affiche le message.
cygwin gcc 2.95.3-5 :
toujours vrais.
debug :
movl -4(%ebp),%eax ; eax = C
incl -4(%ebp) ; C++
cmpl %eax,-4(%ebp) ; Compare C et eax
traduction code type masm/tasm :
mov eax,dword ptr [ebp-4]
inc dword ptr [ebp-4]
cmp dword ptr [ebp-4],eax
release:
comme le compilo considere le test comme toujours vrais : il sort sans
effectuer le test en question et affiche le message.