Указатели в C/C++ всегда смущали людей, поскольку их можно использовать по-разному, и иногда эти способы могут сойти с ума. Понимание этой темы поначалу немного сложно, но как только вы овладеете ею, вы оцените, насколько красиво работает концепция указателей в C и C++. Указатели могут быть одной из причин, по которой работа с такими языками, как Python и Java, поначалу кажется немного странной. Это произошло в моем случае.

Могут быть указатели на константные объекты, константные указатели, константные указатели на константные объекты, указатель на указатель на тип данных, константный указатель на указатель на тип данных и многие другие сумасшедшие случаи. Эти случаи сначала кажутся запутанными, но затем их легко понять.

struct stu x = { 
      .one = 1, .two = 2,
};

Указатель на константный объект

struct stu const *p; == const struct stu *p;
// pointer to a const object
Operation possible :
p = &x;
Operations not possible:
p->one = 11;
/* p can be assigned a new address but it cannot modify the fields of the object it points to.*/

Постоянный указатель

struct stu * const p; //const pointer 
Operations possible:
p->one = 11;
p->two = 12;
Operations not possible:
p = &x;
/* p cannot be assigned a new address but it can modify the fields of the object it points to.*/

Неконстантный указатель на неконстантный объект

struct stu *p; // Non const pointer to a non const object
Operation possible :
p->one = 11;
p = &y; // y is of type stu
/* p can be assigned a new address and can also modify the fields of the object it points to.*/

Константный указатель на константный объект

const struct stu * const p; // const pointer to a const object
Operations possible:
Only dereferencing is possible
Operations not possible:
p = &x;
p->one = 11;
p->two = 12;
/* p cannot be assigned a new address and it cannot modify the fields of the object it points to.*/

В приведенных выше примерах объект x типа stu не является константным, поэтому все приведенные выше примеры будут компилироваться. Но если бы x был типа const, то приведенные ниже операции завершились бы неудачей, поскольку указатель const и неконстантный указатель на неконстантный объект не может указывать на константный объект.

const struct stu x = { .one = 1, .two = 2 };
struct stu *p; //const pointer
p = &x; //Error
struct stu * const q; //non const pointer to non const object
q = &x; //Error

Я рассмотрел наиболее распространенные из них, но по этой теме можно изучить гораздо больше, например, двойные указатели, массивы указателей и т. д.