Folco (./30900) :
J'éspère que tu comprends que je vois ton argumentation comme très limite, même si tu défends très bien les compilateurs ?
Oh, je ne défends pas les compilos, ça me fait suer aussi
Mais quand tu décortiques, souvent même des optimisations "évidentes" reposent sur des présupposés qui ne sont pas vrais dans 100% des cas, et toute la difficulté est justement de détecter ces cas (parfois, c'est simplement infaisable ou carrément impossible). On ne s'en rend pas forcément compte quand on programme en assembleur, parce qu'on en sait beaucoup plus sur le code qu'on écrit qu'un compilateur. Malheureusement, je pense qu'on ne peut pas résoudre ce problème sans changer fondamentalement le langage, ou accepter d'avoir des perfs franchement dégradées.
Folco (./30900) :
En l'occurence, ce que j'ai écrit a une sens très précis, et a une seule façon de s'écrire en code machine pour mon target.
Alors je pense qu'il faut que tu arrêtes de faire du C, ou au minimum que tu décortiques la spéc, parce que tu vas au devant de cruelles désillusions
Contrairement à ce que certains prétendent, le C n'est pas un assembleur portable. Premièrement, parce qu'il est spécifié de manière beaucoup moins stricte et rigoureuse que l'assembleur. Deuxièmement, parce qu'il n'y a aucune garantie sur la correspondance entre le sources C et le code assembleur généré, en-dehors du fait qu'ils sont censés avoir le même effet
suivant les principes de la spéc (qui ne sont pas forcément ceux de la machine sous-jacente). Troisièmement, parce qu'écrire du code C non trivial qui soit réellement portable (à savoir : qui fonctionne de la même façon sur toutes les implémentations) est affreusement difficile : tu peux avoir une architecture qui soit à la fois strictement conforme à la spéc, et suffisamment tordue pour que quasiment tout le monde finisse par tomber dans un piège. Et le pire, c'est qu'il n'y a même pas de moyen automatisé qui garantisse l'absence de code non portable, parce qu'on ne sait détecter qu'une partie des cas de figures.
Il ne faut pas oublier le contexte dans lequel ce langage a été créé : à l'époque il y avait pas mal d'archis différentes et (du point de vue moderne) assez baroques, et pour beaucoup d'applications, on ne pouvait pas se permettre le luxe de privilégier la sécurité aux perfs. Le C était un langage à la syntaxe (faussement) facile, implémentable sur à peu près n'importe quelle machine/OS, avec de bonnes perfs, et laissant suffisamment de liberté aux codeurs pour ne pas les gêner. C'est pour ça qu'il a connu un tel succès, d'ailleurs. Ce qui est embêtant, c'est que maintenant que les priorités ne sont plus les mêmes, il soit toujours aussi répandu.
Et le cas que tu présentes est encore "gentil" comparé à d'autres trucs. J'avais déjà posté, par exemple :
- un compilateur qui, si une variable booléenne est laissée non initialisée, considère que les conditions
var et
!var sont toutes les deux vraies
- le fait qu'il soit impossible, du moins avec GCC, de forcer de manière fiable le séquencement des blocs C et ASM - ce qui veut dire qu'on ne peut pas, par exemple, ne désactiver les interruptions que pendant la section de code qu'on veut
- un compilateur qui supprime carrément une boucle infinie sans condition de sortie (genre
while (1);) [je considère ça comme un bug grave, et apparemment je ne suis pas le seul, mais certains auteurs de compilateur sont d'avis que la spéc le permet]
(on devrait forker vers le topic approprié, je crois ^^)