volatile
est de dire au compilateur de ne pas optimiser la référence, afin que chaque lecture/écriture n'utilise pas la valeur stockée dans le registre mais fasse un véritable accès mémoire. Je peux comprendre que c'est utile pour une variable ordinaire, mais je ne comprends pas comment volatile
affecte un pointeur.
volatile int *p = some_addr;
int a = *p; // CPU always has to load the address, then does a memory access anyway, right?
Quelle est la différence si elle a été déclarée comme int *p = some_addr
?
Un pointeur du formulaire
volatile int* p;
est un pointeur vers un int
que le compilateur traitera comme volatile
. Cela signifie que le compilateur supposera qu'il est possible que la variable pointée par p
ait changé même s'il n'y a rien dans le code source pour suggérer que cela pourrait se produire. Par exemple, si je définis p
pour pointer vers un entier normal, chaque fois que je lis ou écrit *p
, Le compilateur sait que la valeur peut avoir changé de façon inattendue.
Il existe un autre cas d'utilisation pour un volatile int*
: Si vous déclarez un int
comme volatile
, vous ne devez pas le pointer avec un int*
Normal. Par exemple, c'est une mauvaise idée:
volatile int myVolatileInt;
int* ptr = &myVolatileInt; // Bad idea!
La raison en est que le compilateur C ne se souvient plus que la variable pointée par ptr
est volatile
, il peut donc mettre en cache la valeur de *p
Dans un registre de manière incorrecte. En fait, en C++, le code ci-dessus est une erreur. Au lieu de cela, vous devez écrire
volatile int myVolatileInt;
volatile int* ptr = &myVolatileInt; // Much better!
Maintenant, le compilateur se souvient que ptr
pointe vers un volatile int
, Il n'essaiera donc pas (ou ne devrait pas!) D'optimiser les accès via *ptr
.
Un dernier détail - le pointeur dont vous avez parlé est un pointeur vers un volatile int
. Vous pouvez également le faire:
int* volatile ptr;
Cela signifie que le pointeur lui-même est volatile
, ce qui signifie que le compilateur ne doit pas essayer de mettre en cache le pointeur en mémoire ni essayer d'optimiser la valeur du pointeur car le pointeur lui-même pourrait être réaffecté par autre chose (matériel, etc.) Vous pouvez les combiner ensemble si vous souhaitez obtenir cette bête:
volatile int* volatile ptr;
Cela signifie que le pointeur et la pointe peuvent être modifiés de manière inattendue. Le compilateur ne peut pas optimiser le pointeur lui-même et il ne peut pas optimiser ce qui est pointé.
J'espère que cela t'aides!
Ce code volatile int *p = some_addr
déclare un pointeur sur un volatile int
. Le pointeur lui-même n'est pas volatile
.
Dans le cas peu probable où vous auriez besoin que le pointeur soit volatil ainsi que l'int, vous devrez utiliser:
volatile int * volatile p;
Je ne peux pas penser à une situation où vous auriez besoin de l'utiliser.
Sur l'utilité de volatile: Cela est nécessaire, si vous avez besoin de vérifier la mémoire, qui est modifiée par le matériel comme un contrôleur d'interface série. Il trouve son application dans le monde des systèmes embarqués, où vous travaillez très près du matériel sans aucun OS intermédiaire.