Edit global: désolé les gars, je suis tout excité et j'ai écrit beaucoup de bêtises. Juste un vieux coup de gueule.
Je voulais croire que C avait été épargné, mais hélas depuis C11, il a été mis au même niveau que C ++. Apparemment, savoir ce que le compilateur fera avec les effets secondaires dans les expressions nécessite maintenant de résoudre une petite énigme mathématique impliquant un ordre partiel des séquences de code basé sur "est situé avant le point de synchronisation de".
Il se trouve que j'ai conçu et mis en œuvre quelques systèmes embarqués critiques en temps réel à l'époque de K&R (y compris le contrôleur d'une voiture électrique qui pourrait envoyer des personnes s'écraser contre le mur le plus proche si le moteur n'était pas contrôlé, un industriel de 10 tonnes). robot qui pourrait écraser les gens en une pâte s'il n'est pas correctement commandé, et une couche système qui, bien qu'inoffensive, aurait quelques dizaines de processeurs sucer leur bus de données à sec avec moins de 1% de frais généraux du système).
Je suis peut-être trop sénile ou stupide pour faire la différence entre indéfini et non spécifié, mais je pense que j'ai encore une assez bonne idée de ce que signifient l'exécution simultanée et l'accès aux données. À mon avis sans doute informé, cette obsession du C ++ et maintenant des gars C avec leurs langages familiers prenant en charge les problèmes de synchronisation est un rêve de pipe coûteux. Soit vous savez ce qu'est une exécution simultanée, et vous n'avez besoin d'aucun de ces gadgets, soit vous ne l'avez pas, et vous rendriez service au monde en général sans essayer de jouer avec.
Tout ce chargement d'abstractions de barrière de mémoire alléchantes est simplement dû à un ensemble temporaire de limitations des systèmes de cache multi-CPU, qui peuvent tous être encapsulés en toute sécurité dans des objets de synchronisation de système d'exploitation communs comme, par exemple, les mutex et les variables de condition C ++ des offres.
Le coût de cette encapsulation n'est qu'une infime baisse des performances par rapport à ce qu'une utilisation d'instructions CPU spécifiques à grain fin pourrait réaliser dans certains cas.
Le volatile
mot clé (ou un#pragma dont-mess-with-that-variable
malgré tout, en tant que programmeur système, le soin) aurait suffi pour dire au compilateur d'arrêter de réorganiser les accès à la mémoire. Le code optimal peut facilement être produit avec des directives asm directes pour saupoudrer le pilote de bas niveau et le code du système d'exploitation avec des instructions spécifiques au processeur ad hoc. Sans une connaissance approfondie du fonctionnement du matériel sous-jacent (système de cache ou interface de bus), vous êtes de toute façon obligé d'écrire du code inutile, inefficace ou défectueux.
Un ajustement minutieux du volatile
mot - clé et de Bob aurait été tout le monde, sauf l'oncle des programmeurs de bas niveau les plus durs. Au lieu de cela, le gang habituel des monstres mathématiques C ++ a eu une journée de terrain pour concevoir une autre abstraction incompréhensible, cédant à leur tendance typique à concevoir des solutions à la recherche de problèmes inexistants et à confondre la définition d'un langage de programmation avec les spécifications d'un compilateur.
Seulement cette fois, le changement nécessaire pour défigurer un aspect fondamental de C aussi, puisque ces "barrières" devaient être générées même en code C de bas niveau pour fonctionner correctement. Cela, entre autres, a fait des ravages dans la définition des expressions, sans aucune explication ni justification que ce soit.
En conclusion, le fait qu'un compilateur puisse produire un code machine cohérent à partir de ce morceau absurde de C n'est qu'une conséquence éloignée de la façon dont les gars C ++ ont fait face aux incohérences potentielles des systèmes de cache de la fin des années 2000.
Cela a fait un terrible gâchis d'un aspect fondamental de C (définition de l'expression), de sorte que la grande majorité des programmeurs C - qui ne se soucient pas des systèmes de cache, et à juste titre - sont maintenant obligés de s'appuyer sur des gourous pour expliquer la différence entre a = b() + c()
et a = b + c
.
Essayer de deviner ce qu'il adviendra de ce tableau malheureux est une perte nette de temps et d'efforts de toute façon. Indépendamment de ce que le compilateur en fera, ce code est pathologiquement incorrect. La seule chose responsable à en faire est de l'envoyer au bac.
Conceptuellement, les effets secondaires peuvent toujours être retirés des expressions, avec l'effort trivial de laisser explicitement la modification se produire avant ou après l'évaluation, dans une déclaration distincte.
Ce type de code merdique aurait pu être justifié dans les années 80, lorsque vous ne pouviez pas vous attendre à ce qu'un compilateur optimise quoi que ce soit. Mais maintenant que les compilateurs sont devenus plus intelligents que la plupart des programmeurs, il ne reste plus qu'un morceau de code merdique.
Je ne comprends pas non plus l’importance de ce débat indéfini / non spécifié. Soit vous pouvez compter sur le compilateur pour générer du code avec un comportement cohérent, soit vous ne le pouvez pas. Que vous appeliez cela non défini ou non spécifié semble être un point discutable.
À mon avis, sans doute éclairé, C est déjà suffisamment dangereux dans son état K&R. Une évolution utile consisterait à ajouter des mesures de sécurité de bon sens. Par exemple, en utilisant cet outil d'analyse de code avancé, les spécifications forcent le compilateur à implémenter pour générer au moins des avertissements sur le code bonkers, au lieu de générer silencieusement un code potentiellement peu fiable à l'extrême.
Mais à la place, les gars ont décidé, par exemple, de définir un ordre d'évaluation fixe en C ++ 17. Désormais, chaque imbécile logiciel est activement incité à mettre délibérément des effets secondaires dans son code, profitant de la certitude que les nouveaux compilateurs géreront avec empressement l'obscurcissement de manière déterministe.
K&R était l'une des véritables merveilles du monde informatique. Pour vingt dollars, vous avez obtenu une spécification complète de la langue (j'ai vu des personnes seules écrire des compilateurs complets en utilisant simplement ce livre), un excellent manuel de référence (la table des matières vous pointe généralement dans quelques pages de la réponse à votre question), et un manuel qui vous apprendrait à utiliser la langue de manière sensée. Complétez avec des justifications, des exemples et des mots judicieux d'avertissement sur les nombreuses façons dont vous pourriez abuser du langage pour faire des choses très, très stupides.
Détruire cet héritage pour si peu de gains me semble une perte cruelle. Mais encore une fois, je pourrais très bien ne pas voir le point complètement. Peut-être qu'une âme aimable pourrait me diriger vers un exemple de nouveau code C qui tire un avantage significatif de ces effets secondaires?