Que signifie déclarer une variable volatile?

9

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?

Vikaton
la source
1
Si vous lisez votre âge dans une volatilevariable et qu'il est dit 5, et que vous le
relisez l'
@ 5gon12eder, je comprends que volatile signifie que quelque chose est sujet à un changement rapide et facile, mais comment cela fonctionne-t-il? : S
Vikaton
En outre, en fonction de vos indicateurs de compilation, une variable non volatile «pourrait» apparaître dans votre débogueur (par exemple, vous utilisez le code C + Eclipse + gdb), comme: «valeur de sortie optimisée» car la valeur de la variable est maintenant quelque part dans un registre. Si vous ne savez pas comment utiliser les outils / fonctionnalités de débogage du langage assembleur, déclarez simplement votre variable à l'aide du modificateur volatile.

Réponses:

11

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 5une variable et que vous ne la modifiez pas, elle contiendra toujours 5. É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 du 5.

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 changeant 500. Si vous voulez que votre programme lise la nouvelle valeur 500, vous devez que le compilateur ne soit pas trop intelligent sur l'utilisation de la lecture précédente 5. Vous devez lui dire de recharger la valeur à chaque fois. Voilà ce qui volatilefait.

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 efface 3 to 4et écrit 3 to 5.

Lorsque vous allez mettre le score du jeu dans votre histoire, vous pouvez soit:

  1. Notez le dernier score que vous avez lu, en 3 to 4supposant gaiement que cela n'a pas changé (ou si cela ne vous dérange pas), ou
  2. Promenez-vous de l'autre côté de la table pour lire la partition actuelle (qui se trouve être 3 to 5maintenant) et revenez en arrière. Voilà comment volatileagit une variable.
Jerry101
la source
11

volatile signifie deux choses:

  1. 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.

  2. 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:

i = 2; 
i = i; 

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 setjmppuis longjmpest 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.

gnasher729
la source
Il y a ici quelques problèmes subtils. Un problème subtil est que vous avez caractérisé les lectures volatiles comme une caractéristique de la variable alors qu'en fait elles sont une caractéristique de la façon dont la variable est accédée . Si nous avons la variable iet la valeur pi = &i, alors x = *piune lecture est effectuée i, mais cette lecture n'est pas garantie d'avoir une sémantique volatile.
Eric Lippert
1
@EricLippert: Si iest déclaré comme volatile int ialors pidoit être déclaré comme volatile int *pi, dans quel cas *piest un accès volatile, non?
Jon Purdy
2

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 effectuer statement_Adans son intégralité, puis statement_B, et enfin statement_C. L'implémentation ne se souvient pas que vous avez attribué agela valeur 5. Chaque déclaration que les références agedoivent plutôt accéder à la valeur de cette variable.

Le volatilemot 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-ifrègle, la séquence statement_A; statement_B; statement_C;peut être implémentée en exécutant une partie de statement_C, puis une partie de statement_A, puis tout statement_B, puis le reste statement_Aet enfin le reste de statement_C.

Ceux que, si les règles ne sont pas applicables à des volatilevariables. En ce qui concerne les volatilevariables 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

qu'est-ce que cela signifie lorsque le compilateur n'optimise pas l'adresse mémoire?

«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.

David Hammen
la source
1

(non) volatile est une indication pour le compilateur comment optimiser le code (du point de vue du code assembleur généré):

  • non volatile signifie que votre compilateur actuel décide où la variable sera située ou comment la valeur de la variable est transférée à un sous-programme
    • dans une adresse mémoire fixe,
    • sur la pile [par rapport au stackpointer actuel du processeur],
    • sur le tas [par rapport au pointeur de base actuel du processeur],
    • dans un registre processeur,
    • ...
  • volatile signifie que le compilateur ne peut pas optimiser la variable car quelque chose d'autre en dehors du contrôleur principal-cpu-s (c'est-à-dire un io-processeur séparé) peut changer cette valeur.
k3b
la source
0

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.

old_timer
la source