9
votes

Analyse profonde du qualificatif Const en C

Où une variable const est-il stocké exactement et comment change-t-il? Dites par exemple: xxx

si la réponse est le segment de code, alors comment le code suivant fonctionne-t-il ?? xxx

Ce code fonctionne bien. .. Comment il est possible de changer une mémoire en lecture seule? Comment ça se passe vraiment stocké? S'il vous plaît expliquer cela en détail.


3 commentaires

Avez-vous vérifié ceci: Stackoverflow.com/questions/3801557/... ?


Je peux vous assurer que votre segment de 2e code est comportement indéfini


Je crois que la plupart des compilateurs modernes donneraient un avertissement lors de la transmission de la ligne "p = & j" avertissant des différents qualificateurs de const, car vous attribuez un pointeur à Const Int à un pointeur à int. Donc, la morale de l'histoire est la suivante: toujours utiliser -werror


9 Réponses :


1
votes

Cela ne devrait vraiment pas fonctionner.

Les constantes ne sont généralement pas stockées nulle part. Ils sont étendus en ligne.

Il est possible que votre compilateur soit gentil avec vous et vous donnant un lieu de mémoire à modifier, mais normalement, c'est impossible.

Quels avertissements obtenez-vous? J'imagine que vous devez obtenir un peu ...


1 commentaires

Ils ont stocké des autres variables, mais peuvent être remplacées par des lignes en ligne par optimiseur.



2
votes

Je ne sais pas où il est stocké, car c'est défini par la mise en œuvre, mais votre code entraîne un comportement non défini.


0 commentaires

1
votes

C'est totalement à la hauteur du rédacteur du compilateur Qu'est-ce qui arrive à la const, et il variera en fonction de l'optimisation que vous demandez.

Dans votre premier exemple, les constantes ne sont jamais utilisées pour que le compilateur ne les ignorera probablement pas complètement.

Dans votre deuxième exemple Lorsque vous utilisez "adresse", il doit le stocker quelque part - probablement au début de la pile.

C est conçu pour remplacer les instructions de langage de l'assemblage, et pour la rédaction de code de type OS Kernal et du pilote de périphérique, vous permet de faire toutes sortes de choses et vous assume que vous savez ce que vous faites lorsque vous commencez à jouer avec des pointeurs.


0 commentaires

1
votes

Le compilateur détermine si l'adresse de la constante est nécessaire. Si ce n'est pas le cas, il est (généralement) entré en ligne dans le segment de code, car c'est (généralement) plus rapide que la mémoire de référencement.

Si l'adresse est nécessaire, la constante est stockée comme s'il s'agissait d'une variable non constituée dans la portée actuelle (relativement en fonction du compilateur). En d'autres termes, Global Consts est généralement stocké dans votre segment de données, fonction (paramètre ou déclaré) constons généralement être stocké sur la pile.

pense à cela comme une variable de registre. C'est dans votre registre de votre CPU, si vous connaissez cela. C'est dans votre inscription de votre CPU jusqu'à ce que vous ayez besoin de son adresse. Ensuite, il est mis dans un espace adressable.

La vraie question est l'initialisation - si vous avez besoin de son adresse et est donc réellement allouée, alors où est-il initialisé? Il y a quelque chose pour vous de réfléchir.


0 commentaires

11
votes

Le mot-clé const indique une variable en lecture seule (c'est-à-dire que, ne peut pas être modifiée au moment de l'exécution). Il n'indique pas une constante de temps de compilation. Par conséquent, tous les attributs habituels des variables s'appliquent; Plus précisément, il s'agit d'un espace de stockage adressable alloué.

Contrairement à #define , votre constante n'est pas nécessairement inline par le compilateur. Au contraire, le compilateur créera un symbole correspondant à votre déclaration const dans le fichier d'objet afin de pouvoir être accessible à partir d'autres fichiers de code - rappelez-vous que les objets const ont une liaison externe par Par défaut en C (Bien que certains compilateurs feront toujours en ligne la valeur constante dans le fichier dans lequel il est défini).

La raison pour laquelle l'extrait de code que vous avez posté "WORKS" est parce que l'opérateur unaire & peut être appliqué à n'importe quelle lvalue, qui comprend un objet const . Bien que le comportement soit indéfini, je soupçonne que votre compilateur détecte cette utilisation et que votre déclaration const est donnée dans l'espace d'adresses et ne l'affiche pas, même dans le fichier, il est déclaré.

edit: Voir aussi: http: // publications.gbdirect.co.uk/c_book/chapter8/const_and_volatile.html

Regardons ce que l'on veut dire quand const est utilisé. C'est vraiment assez simple: consiste signifie que quelque chose n'est pas modifiable, donc un objet de données qui est déclaré avec const dans une partie de son Les spécifications de type ne doivent pas être attribué à de quelque manière que ce soit pendant la course d'un programme. Il est très probable que La définition de l'objet sera contenir un initialiseur (sinon, Puisque vous ne pouvez pas l'affecter, comment cela aurait-il jamais une valeur?), mais cela n'est pas toujours le cas. Par exemple, Si vous accédez à un port matériel à une adresse mémoire fixe et promise seulement à lire, alors ce serait déclaré être const mais pas initialisé.

Prendre l'adresse d'un objet de données d'un type qui n'est pas const et le mettre dans un pointeur à la version de Const-qualifiée de la même type est à la fois sûr et explicitement permis; Vous pourrez utiliser le pointeur pour inspecter l'objet, mais pas Modifiez-le. Mettre l'adresse d'un Const Type dans un pointeur sur le Type non qualifié est beaucoup plus dangereux et par conséquent interdit (Bien que vous puissiez entrer cela par en utilisant une distribution). Par exemple ...


3 commentaires

C'est une excellente réponse. Je n'ai bien compris que ce que const en C lorsque j'ai rencontré une variable déclarée const volatile (c'était un registre matériel). Après mon moment initial WTF, j'ai réalisé que const signifie simplement que vous , le programmeur, promettez de ne pas le changer. Si vous vous attendez à ce qu'il change par d'autres moyens, vous avez besoin du volatile . Mais il n'est pas interprété par le compilateur en tant que constante de temps de compilation (comme dans C ++ , je pense).


@Detly, une variable Const ne peut pas apparaître dans un endroit où une expression constante est synontiquement (ce qui est effectivement autorisé pour certains d'entre eux en C ++). Le compilateur peut toujours le considérer comme une constante de temps de compilation à d'autres fins - et le fait probablement.


@Aprogrammer - En effet, c'est une meilleure phrasalisation. Le compilateur ne peut pas le considérer comme une constante de temps de compilation (ou une constante d'exécution) si elle est également déclarée volatile.



1
votes

Le deuxième code ne devrait pas compiler du tout. Et les compilateurs que j'ai ici sont d'accord: GCC donne une erreur avec des erreurs -pedantic (dont le but est de se transformer en erreur de diagnostics obligatoires que Historiquement GCC n'a pas considéré comme une erreur), XLC donne une erreur aussi.

Si vous souhaitez une référence: 6.3.16.1 dans la norme C90 décrit lorsqu'une attribution est possible:

Les deux opérandes sont des pointeurs vers des versions qualifiées ou non qualifiées de types compatibles, et le type pointé à gauche a tous les qualificatifs du type pointé vers le droit

et C99 comme une contrainte similaire.


0 commentaires

1
votes

Lorsque vous déclarez (non-externe, non-argument) et initialisez la variable comme const , cela signifie que la variable n'est pas réelle. Donc, le compilateur est libre de le placer à la seule section. Bien que cela puisse être modifiable physiquement (si le matériel le permet). Ou non modifiable, s'il est protégé par MMU ou placé dans la ROM dans l'application autonome.

standard n'apparte pas, que devrait-il arriver si vous essayez d'écrire const (cela s'appelle «comportement indéfini»), de sorte que tout peut se produire: il peut être écrit, non écrit, causer une exception, suspendre ou quelque chose d'autre que vous ne pouvez pas imaginer. C non aussi paranoïaque que, disons, ADA, et tout comportement non couché est à programmer, pas compilateur ou RTL.

Comme beaucoup l'indiquent, il est inliné dans la plupart des cas (si le compilateur sache qu'en ligne), mais conserve toujours les attributs des variables, tels que l'adresse (et vous pouvez obtenir un pointeur), la taille. Si toutes les déclarations de const sont éliminées et que le stockage pour const sera également éliminé par Compiler (s'il est statique ou local) ou de la liaison (si elle est globale).

Remarque, les pointeurs locaux peuvent également être éliminés si leurs emplacements peuvent être calculés en temps de compilation. Les écrivies également aux variables locales peuvent être éliminées si elles ne sont pas lues après cela. Votre extrait ne peut avoir aucun code du tout.

La variable locale automatique peut être compilée dans le stockage statique si le compilateur prouve qu'une seule instance de celle-ci est nécessaire. Comme const n'est pas modifiable, il est également compilé dans le stockage statique, mais peut être éliminé comme indiqué ci-dessus.

Dans tous vos exemples, tous les constons peuvent d'abord être mis de stockage statique (Const Section), puis facilement éliminés.


0 commentaires

7
votes

Modification de votre code pour imprimer la valeur:

#include <stdio.h>

main()
{
   const int j=20;
   int *p;
   p=&j;
   (*p)++;
    printf("%d\n", j);
   return 0 ;
}


0 commentaires

4
votes

par la norme C ( N1256 brouillon):

6.7.3 Type Qualificateurs
...
3 Les propriétés associées à des types qualifiés ne sont significatives que pour les expressions que sont des lvalues. 114)
...
5 Si une tentative est faite pour modifier un objet défini avec un type de Cons-qualifié via une utilisation d'une lvalue avec type non qualifié non constitué, le comportement est indéfini. Si une tentative est fait pour se référer à un objet défini avec un type qualifié volatile grâce à une utilisation d'un lvalue Avec type qualifié non volatile, le comportement est indéfini. 115)
...
114) La mise en œuvre peut placer un objet const qui n'est pas volatile dans une région en lecture seule de espace de rangement. De plus, la mise en œuvre n'a pas besoin d'allouer de stockage pour un tel objet si son adresse est jamais utilisé.

115) Ceci s'applique à ces objets qui se comportent comme s'ils étaient définis avec des types qualifiés, même s'ils sont jamais réellement défini comme des objets du programme (comme un objet à une entrée / sortie mappée de mémoire adresse).

En bref, un objet const objet qualifié peut être stocké dans une zone différente de la non- const objets qualifiés, mais pas nécessairement .

Le qualificatif const est une instruction au compilateur pour rejeter le code qui tente de modifier directement cet objet; Les tentatives de modification de l'objet indirectement (comme vous le faites dans la deuxième extrait de code) entraînent un comportement non défini, ce qui signifie tout résultat est possible.


0 commentaires