web-dev-qa-db-fra.com

Pourquoi un pointeur point à volatile, comme "volatile int * p", est-il utile?

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?

69
Infinite

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!

128
templatetypedef

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.

9
markgz

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.

1
sdiedrichsen