En C, les variables const sont-elles garanties distinctes en mémoire?

En parlant de littéraux de chaîne, la norme C99 dit (6.4.5.6):

Il n’est pas précisé si ces tableaux sont distincts à condition que leurs éléments aient les valeurs appropriées. Si le programme tente de modifier un tel tableau, le comportement n’est pas défini.

Je n’ai pu trouver ni un avertissement similaire ni une garantie explicite pour les variables const. Est-ce que l’expression &x == &y dans le contexte const int x=12; const int y=12; const int x=12; const int y=12; évaluer à 1 ? Qu’en est-il d’une variable const et d’un littéral de chaîne (c’est-à-dire que &x == "\014\000\000" garanti à 0 même sur une plate-forme little-endian 32 bits)?

Pour ce qui en vaut la peine, la section “Littéraux de chaîne” de cet article donne le contexte de la question.

Dans la norme, l’égalité est traitée au § 6.5.9 “Opérateurs d’égalité”, & au § 6.5.3.2 “Opérateurs d’adresse et d’indirection”, et const est traitée au § 6.7.3 “Qualificateurs de type”. Le passage pertinent concernant l’égalité de pointeur est le § 6.5.9.6:

Deux pointeurs se comparent égaux si et seulement si les deux sont des pointeurs nuls, tous deux sont des pointeurs sur le même object (y compris un pointeur sur un object et un sous-object à son début) ou une fonction, [ou des pointeurs au-delà de la fin d’un tableau]

La seule définition de & est que “Le unary & operator donne l’adresse de son opérande. […] Le résultat est un pointeur sur l’object ou la fonction désigné par son opérande. ”(§6.5.3.2.3). Il n’existe malheureusement pas de définition formelle du mot «adresse»; mais les objects distincts (pour l’égalité définie par == ) ont des adresses distinctes, car ces adresses sont des pointeurs distincts par la définition d’égalité ci-dessus.

En ce qui concerne la signification de const , le § 6.7.3 n’indique pas que const a une incidence sur ce qui fait un object (qui est “une région de stockage de données dans l’environnement d’exécution, dont le contenu peut représenter des valeurs” au § 3.14. ). Une note de bas de page indique en outre que «l’implémentation n’a pas besoin d’allouer de stockage pour un tel object si son adresse n’est jamais utilisée». Bien que cela ne soit pas normatif, cela indique clairement que si l’adresse est utilisée, la mémoire doit être allouée pour chaque object .

Notez que si les objects sont const volatile , il est assez clair (aussi clair que volatile puisse l’être) qu’ils ne peuvent pas avoir la même adresse, car const volatile objects const volatile sont modifiables par l’implémentation. (Le § 6.7.3.10 présente un exemple d’utilisation de const volatile .)

Même dans le cas non volatile, const indique uniquement que cette partie du programme n’est pas autorisée à modifier l’object, pas que l’object est en lecture seule en général. Pour fusionner le stockage d’un object const avec autre chose, l’implémenteur audacieux devrait garantir que rien ne peut modifier l’object. Ceci est assez difficile pour un object avec un lien externe dans une implémentation avec une compilation séparée (mais bien sûr, nous nous éloignons de la norme pour entrer dans le territoire qui n’arrivera pas dans la pratique).

S’il s’agit d’écrire un programme C, vous pouvez augmenter vos chances en donnant aux objects différentes valeurs:

 const int x = __LINE__; const int y = __LINE__; 

S’il s’agit d’un modèle théorique de C, je choisirais de rendre les objects distincts. Vous devrez justifier ce choix en résumant les réponses ici dans un paragraphe de (la version étendue de) votre document.

Par contre, s’il s’agit d’écrire un compilateur d’optimisation, je doute que la fusion de constantes dans le monde réel nuise à de nombreux programmes. Je préférerais fusionner dans un compilateur intégré, où les utilisateurs sont habitués à jouer en toute sécurité avec des cas extrêmes et où la mémoire sauvegardée pourrait être non négligeable. Je m’opposerais à la fusion dans une plate-forme hébergée où tout gain serait négligeable.

(Références de N1256, alias C99 + TC3. Je ne pense pas que la version fasse une différence.)

Autant que je sache, la norme n’autorise pas deux objects nommés de n’importe quel type à avoir la même adresse (à l’exception des membres d’un syndicat). À partir de 6.5.9 / 6:

Deux pointeurs se comparent égaux si et seulement si les deux sont des pointeurs nuls, les deux sont des pointeurs sur le même object …

Les littéraux de chaîne ne sont pas des variables const, donc votre question secondaire est sans object, et je ne vois pas en quoi 32 bits et finalité ont à voir avec cela.

Dans

 const int x=12; const int y=12; 

x et y sont des variables différentes (qualifiées de const) et ont donc des adresses différentes.

La même chose pour l’autre exemple.

Notez que const est un qualificatif pour un object. En ce qui concerne la disposition de la mémoire, cela ne fait aucune différence que ce soit là ou non.

6.4.5 / 6 dit des tableaux correspondant aux littéraux de chaîne:

Il n’est pas précisé si ces tableaux sont distincts à condition que leurs éléments aient les valeurs appropriées.

C’est donc une règle spécifique permettant de replier les littéraux de chaîne. Je ne connais rien dans la norme qui dise la même chose pour d’autres objects.