Gilliek
28déc/103

Clang vs GCC

Mon ami Rolinh a déjà posté un billet sur une bizarrerie entre Clang et GCC. Eh bien hier soir, je suis tombé sur une autre assez spéciale.

Pour la petite histoire, j'aidais quelqu'un sur un forum et j'ai compilé son code avec Clang et avec Gcc et le résultat obtenue était différent.

Note : Ici, on ne s'intéresse pas à la qualité du code.

Voici le code :

int triplePointeur(int *pointeurSurNombre);

int main()
{
	int nombre = 5;
	triplePointeur(&nombre);
	printf("%d %dnn", nombre, triplePointeur(&nombre));

	return 0;
}

int triplePointeur(int *pointeurSurNombre)
{
	int a = 4;
	int b = 2;
	*pointeurSurNombre *= 3;
	return a + b;
}

Avec GCC ça donne :

$ gcc -Wall -o test test.c
$ ./test
45 6

On a une première modification de la variable nombre avec le premier appel de la fonction triplePointeur. On a 3 * 5 = 15. Ensuite, on réappelle triplePointeur dans le printf et on a donc  nombre = 3 * 15 = 45.

Et maintenant avec Clang :

$ clang -Wall -o test test.c
$ ./test
15 6

Et là, surprise, on obtient 15 !

Pour la réponse à cette énigme (voir commentaires, et au passage merci au posteur anaonyme) :

En fait, l'ordre de calcul des paramètres n'est pas défini dans le langage C. GCC calcule de droite à gauche, donc la variable nombre est modifiée deux fois. Quant à Clang, lui il les calcule de gauche de à droite. Du coup, nombre est affichée avant d'être modifiée une seconde fois.

Commentaires (3) Trackbacks (0)
  1. L’ordre de calcul des paramètres d’une fonction n’est pas définie dans le langage C. Il ne faut donc JAMAIS partir du paramètre qu’il sera effectué de gauche à droite. Tu dis que le premier résultat est correct, mais le second l’est tout autant. Si tu écrivais de droite à gauche, tu trouverais peut-être le premier résultat surprenant.

    Si, par exemple, tu veux calculer le nombre qui se trouve en haut d’un stack à la puissance du second (en les retirant), il ne faut pas faire
    float res = pow(remove(), remove());
    car dans ce cas, tu ne sais pas dans quel ordre ils sont retirés. Je te donne en exercice la solution à ce problème.

    • Merci pour ta réponse.

      Je pensais que l’ordre de calcul des paramètres étaient défini dans le langage C, mais apparemment non :-)

  2. Pour évaluer printf(« %d %dnn », nombre, triplePointeur(&nombre));.
    Le compilateur est obbligé d’évaluer d’abord triplePointeur(&nombre) quel que soit le compilateur puiqu’il doit connaitre les paramètres de la fonction.
    Le sens classique (celui de GCC) veut qu’ensuite on évalue printf(« %d %dnn », nombre, resultat_triplePointeur); Clang lui, évalue printf(« %d %dnn », sauvegarde_de_nombre, resultat_triplePointeur). Clang a tout aussi raison que gcc mais ne gaspille t’il pas bêtement un emplacement mémoire?


Leave a comment

(required)

Aucun trackbacks pour l'instant