Разница действительно сводится к разнице между const
и volatile
. Единственное, что объединяет эти два понятия, это синтаксис. const
поддерживается компилятором и говорит, что «программист не может изменить это». volatile
говорит, что «эти данные могут быть изменены кем-то другим», и поэтому компилятор не будет делать никаких предположений относительно этих данных. Без volatile
компилятор мог бы сказать: «Я поместил эти данные из памяти в регистр, и, поскольку я ничего не сделал с этими данными, я уверен, что это то же самое, и мне не нужно считывать их в регистр снова." Когда данные помечены как volatile
, компилятор не будет делать такое предположение (потому что кто-то другой мог изменить данные) и поэтому будет перечитывать данные в регистр.
Теперь, вы спрашиваете разницу между
int *const p;
и
int *volatile q;
или разница между
const int* p;
и
volatile int* q;
В первом случае: p
- это указатель на int
, и где эти точки указателя не могут быть изменены программистом, тогда как q
- это указатель на int
, и где эти точки указателя могут быть изменено кем-то кроме программиста, поэтому компилятор не делает никаких предположений об этом указателе.
Итак:
int *const p = (int*)malloc(sizeof(int));
int *volatile q = (int*)malloc(sizeof(int));
*p = 17; // legal;
p = (int*)malloc(sizoef(int)); // not legal
*q = 17; // legal;
q = (int*)malloc(sizeof(int)); // legal
В последнем случае: p
- указатель на int
, и то, на что указывает p
, не может быть изменено программистом, тогда как q
- указатель на int
и что q
указывает на то, что может быть изменен кем-то кроме программиста, поэтому компилятор не делает никаких предположений относительно этих данных.
int i = 17;
int j = 34;
const int *p = &i;
volatile int *q = &i;
*p = 51; // not legal
p = &j; // legal
*q = 51; // legal
q = &j; // legal