Historiquement (peut-être en réécrivant certaines parties), c'était le contraire. Sur les tout premiers ordinateurs du début des années 1970 (peut - être PDP-11 ) exécutant un C embryonnaire prototypique (peut-être BCPL ), il n'y avait pas de MMU ni de protection de mémoire (qui existaient sur la plupart des ordinateurs centraux IBM / 360 plus anciens ). Ainsi , chaque octet de mémoire (y compris ceux qui manipulent des chaînes littérales ou code machine) pourrait être remplacé par un programme erroné (imaginez un programme changeant certains %
à /
une printf (3) chaîne de format). Par conséquent, les chaînes et constantes littérales étaient accessibles en écriture.
Adolescent en 1975, j'ai codé au musée du Palais de la Découverte à Paris sur des ordinateurs anciens des années 1960 sans protection mémoire: IBM / 1620 n'avait qu'une mémoire centrale - que vous pouviez initialiser via le clavier, il fallait donc taper plusieurs dizaines de chiffres pour lire le programme initial sur des bandes perforées; Le CAB / 500 avait une mémoire à tambour magnétique; vous pouvez désactiver l'écriture de certaines pistes via des commutateurs mécaniques près du tambour.
Plus tard, les ordinateurs ont obtenu une forme d'unité de gestion de la mémoire (MMU) avec une certaine protection de la mémoire. Il y avait un périphérique interdisant au CPU d'écraser une sorte de mémoire. Ainsi, certains segments de mémoire, notamment le segment de code (aka .text
segment) sont devenus en lecture seule (sauf par le système d'exploitation qui les a chargés à partir du disque). Il était naturel pour le compilateur et l'éditeur de liens de placer les chaînes littérales dans ce segment de code, et les chaînes littérales sont devenues en lecture seule. Lorsque votre programme a essayé de les écraser, c'était mauvais, un comportement non défini . Et avoir un segment de code en lecture seule dans la mémoire virtuelle offre un avantage significatif: plusieurs processus exécutant le même programme partagent la même RAM ( mémoire physiquepages) pour ce segment de code (voir l' MAP_SHARED
indicateur pour mmap (2) sous Linux).
Aujourd'hui, les microcontrôleurs bon marché ont une mémoire en lecture seule (par exemple leur Flash ou ROM) et y conservent leur code (et les chaînes littérales et autres constantes). Et les vrais microprocesseurs (comme celui de votre tablette, ordinateur portable ou de bureau) ont une unité de gestion de mémoire sophistiquée et un mécanisme de cache utilisé pour la mémoire virtuelle et la pagination . Ainsi, le segment de code du programme exécutable (par exemple dans ELF ) est mappé en mémoire en tant que segment en lecture seule, partageable et exécutable (par mmap (2) ou execve (2) sous Linux; BTW vous pouvez donner des directives à ldpour obtenir un segment de code accessible en écriture si vous le vouliez vraiment). L'écrire ou en abuser est généralement un défaut de segmentation .
La norme C est donc baroque: légalement (uniquement pour des raisons historiques), les chaînes littérales ne sont pas des const char[]
tableaux, mais uniquement des char[]
tableaux dont l'écrasement est interdit.
BTW, peu de langues actuelles autorisent l'écrasement des littéraux de chaîne (même Ocaml qui, historiquement et mal) avait des chaînes littérales inscriptibles, a récemment changé ce comportement en 4.02, et a maintenant des chaînes en lecture seule).
Les compilateurs C actuels sont capables d'optimiser et d'avoir "ions"
et de "expressions"
partager leurs 5 derniers octets (y compris l'octet nul final).
Essayez de compiler votre code C dans un fichier foo.c
avec gcc -O -fverbose-asm -S foo.c
et regardez à l'intérieur du fichier assembleur généré foo.s
par GCC
Enfin, la sémantique de C est suffisamment complexe (en savoir plus sur CompCert et Frama-C qui essaient de le capturer) et l'ajout de chaînes littérales constantes inscriptibles le rendrait encore plus obscur tout en rendant les programmes plus faibles et encore moins sécurisés (et avec moins comportement défini), il est donc très peu probable que les futures normes C acceptent des chaînes littérales inscriptibles. Peut-être au contraire en feraient-ils des const char[]
tableaux comme ils devraient être moralement.
Notez également que pour de nombreuses raisons, les données mutables sont plus difficiles à gérer par l'ordinateur (cohérence du cache), à coder, à comprendre par le développeur, que les données constantes. Il est donc préférable que la plupart de vos données (et notamment les chaînes littérales) restent immuables . En savoir plus sur le paradigme de programmation fonctionnelle .
Dans les anciens jours Fortran77 sur IBM / 7094, un bogue pouvait même changer une constante: si vous CALL FOO(1)
et s'il vous FOO
arrivait de modifier son argument passé par référence à 2, l'implémentation aurait pu changer d'autres occurrences de 1 en 2, et c'était vraiment un bug vilain, assez difficile à trouver.