De nombreux programmes de bas niveau utilisent le mot-clé volatile pour les types de mappage de la mémoire et autres, mais je suis un peu confus quant à ce qu'il fait vraiment en arrière-plan. En d'autres termes, qu'est-ce que cela signifie lorsque le compilateur n'optimise pas l'adresse mémoire?
9
volatile
variable et qu'il est dit 5, et que vous leRéponses:
volatile
signifie qu'un autre processeur ou périphérique d'E / S ou quelque chose peut changer la variable sous vous.Avec une variable ordinaire, les étapes de votre programme sont la seule chose qui la changera. Ainsi, par exemple, si vous lisez
5
une variable et que vous ne la modifiez pas, elle contiendra toujours5
. Étant donné que vous pouvez compter sur cela, votre programme n'a pas à prendre le temps de relire la variable la prochaine fois que vous souhaitez l'utiliser. Le compilateur C ++ est intelligent pour générer du code qui se souvient simplement du5
.Mais vous pouvez le lire comme
5
, alors peut-être que le système charge les données du disque dans cette mémoire, en les changeant500
. Si vous voulez que votre programme lise la nouvelle valeur500
, vous devez que le compilateur ne soit pas trop intelligent sur l'utilisation de la lecture précédente5
. Vous devez lui dire de recharger la valeur à chaque fois. Voilà ce quivolatile
fait.Une analogie pour les enfants de 5 ans
Disons que vous mettez une grande feuille de papier sur une table. Dans un coin du papier, vous écrivez le score d'un jeu en cours,
3 to 4
. Ensuite, vous allez de l'autre côté de la table et commencez à écrire une histoire sur le jeu. Votre ami qui regarde le jeu met à jour le score dans ce coin au cours du jeu. Elle efface3 to 4
et écrit3 to 5
.Lorsque vous allez mettre le score du jeu dans votre histoire, vous pouvez soit:
3 to 4
supposant gaiement que cela n'a pas changé (ou si cela ne vous dérange pas), ou3 to 5
maintenant) et revenez en arrière. Voilà commentvolatile
agit une variable.la source
volatile
signifie deux choses:La valeur de la variable peut changer sans qu'aucun de vos codes ne la modifie. Par conséquent, chaque fois que le compilateur lit la valeur de la variable, il ne peut pas supposer qu'elle est la même que la dernière fois qu'elle a été lue ou qu'elle est la même que la dernière valeur stockée, mais elle doit être relue.
L'acte de stocker une valeur dans une variable volatile est un "effet secondaire" qui peut être observé de l'extérieur, de sorte que le compilateur n'est pas autorisé à supprimer l'acte de stocker une valeur; par exemple, si deux valeurs sont stockées dans une ligne, le compilateur doit en fait stocker la valeur deux fois.
Par exemple:
Le compilateur doit stocker le numéro deux, lire la variable i, stocker la variable qu'il a lue dans i.
Il existe une autre situation: si une fonction utilise
setjmp
puislongjmp
est appelée, toutes les variables locales volatiles de la fonction sont garanties d'avoir la dernière valeur stockée - ce n'est pas le cas avec les variables locales non volatiles.la source
i
et la valeurpi = &i
, alorsx = *pi
une lecture est effectuéei
, mais cette lecture n'est pas garantie d'avoir une sémantique volatile.i
est déclaré commevolatile int i
alorspi
doit être déclaré commevolatile int *pi
, dans quel cas*pi
est un accès volatile, non?Explication abstraite
C et C ++ ont tous deux un concept de machine abstraite . Lorsque le code utilise la valeur d'une variable, la machine abstraite indique que l'implémentation doit accéder à la valeur de cette variable. Le code du formulaire
statement_A; statement_B; statement_C;
doit être exécuté exactement dans l'ordre spécifié. Les expressions communes à ces trois instructions doivent être recalculées chaque fois qu'elles se produisent.Selon les machines abstraites, compte tenu de la séquence d'instructions
statement_A; statement_B; statement_C;
, l'implémentation doit d'abord effectuerstatement_A
dans son intégralité, puisstatement_B
, et enfinstatement_C
. L'implémentation ne se souvient pas que vous avez attribuéage
la valeur 5. Chaque déclaration que les référencesage
doivent plutôt accéder à la valeur de cette variable.Le
volatile
mot clé ne serait pas nécessaire si les implémentations exécutaient strictement du code C ou C ++ selon les spécifications de la machine abstraite. Les machines abstraites C et C ++ n'ont aucun concept de registres, aucun concept de sous-expressions communes et l'ordre d'exécution est strict.Les deux langues ont aussi que, si les règles. Une implémentation est conforme à la norme tant qu'elle se comporte comme si elle avait exécuté des choses conformément à la spécification de machine abstraite. Le compilateur peut supposer que les variables non volatiles ne modifient pas les valeurs entre les affectations. Tant qu'elle ne viole pas la
as-if
règle, la séquencestatement_A; statement_B; statement_C;
peut être implémentée en exécutant une partie destatement_C
, puis une partie destatement_A
, puis toutstatement_B
, puis le restestatement_A
et enfin le reste destatement_C
.Ceux que, si les règles ne sont pas applicables à des
volatile
variables. En ce qui concerne lesvolatile
variables et les fonctions, une implémentation doit faire exactement ce que vous lui avez dit de faire, et exactement dans l'ordre dans lequel vous lui avez dit de faire les choses.Il y a un inconvénient à la spécification abstraite de la machine: c'est lent. Un aspect positif de C et C ++ par rapport à d'autres langages est qu'ils sont assez rapides. Ce ne serait pas le cas si le code était exécuté par ces machines abstraites. Les que, si les règles sont ce qui permettent C et C ++ pour être si rapide.
Réponse ELI5
«Optimiser» une adresse mémoire est un concept avancé, quelque chose qui ne relève pas des capacités d'un enfant de cinq ans. Les enfants de cinq ans conformes feront exactement ce que vous leur dites de faire, ni plus, ni moins. Avec
volatile
, vous dites à l'implémentation d'agir comme si elle était cinq: pas de réflexion, pas d'optimisations sophistiquées. Au lieu de cela, l'implémentation doit faire exactement ce que le code lui dit de faire.la source
(non) volatile est une indication pour le compilateur comment optimiser le code (du point de vue du code assembleur généré):
la source
Les réponses semblent assez cohérentes mais il manque un point important. Vous dites au compilateur que vous souhaitez allouer de l'espace et pour chaque accès, lisez OU ÉCRIRE, vous voulez qu'il effectue cet accès. Nous ne voulons pas qu'il optimise ces accès ou cette variable pour une raison quelconque.
Oui, une des raisons est que quelqu'un d'autre pourrait changer cette valeur pour nous. Une autre raison est que nous pourrions changer cette valeur pour quelqu'un d'autre. Que quelqu'un d'autre soit celui qui le change pour nous ou celui pour lequel nous le changeons peut être matériel / logique ou logiciel. Il est souvent utilisé pour définir les accès aux registres de contrôle et d'état dans les programmes embarqués bare metal, en écriture ou en lecture depuis le matériel. Ainsi que le logiciel parlant au logiciel expliqué dans d'autres réponses.
Vous verrez également volatile utilisé pour contrôler quand et dans quel ordre les accès se produisent, si vous essayez de chronométrer une section de code, et que vous n'utilisez pas volatile les variables en question (heure de début, heure de fin et différence) doivent seulement être calculé vers la fin, le compilateur est libre de déplacer l'une ou l'autre des mesures de temps (pas là où nous les avons placées), non pas qu'il ne puisse pas être volatil, mais l'expérience le montre moins probable.
À l'occasion, vous le verrez utilisé simplement pour brûler le temps, un clignotant à LED élémentaire, le monde bonjour du métal nu, pourrait utiliser un volatile pour une variable qui compte en grand nombre juste pour brûler du temps pour que l'œil humain puisse voir la led changer d'état. Exemples plus avancés utilisant ensuite des minuteries ou d'autres événements pour graver l'heure.
la source