C/C++

Чем отличается переменная *a от простой a в C++?

Да, я знаю, что такое указатели и сам их изучал. Я знаю, когда ставится звёздочка. Но не понял ее смысла. Насколько я понял, звёздочка предназначена для того, чтобы показывать значение указателя?

Пожалуйста, постарайтесь объяснить мне предозначение звездочки C++ легким языком, как будто я учу эту тему опять. Уже перепробовал множество сайтов, везде одно и тоже.
Изучал? Обновите полученные ранее знания...

int var = 5; // объявление переменной типа int

int* ptr = nullptr; // объявление указателя

ptr = &var; // операция взятия адреса (ptr указывает на var)

int val = *ptr; // операция разыменования указателя (val присвоено значение 5)

void* box = nullptr; // пустой указатель (указатель на void)

double x = 2.5; // объявление переменной типа double

short y = 8; // объявление переменной типа short

box = &x; // операция взятия адреса переменной x

double* x_ptr = (double*)box; // требуется явное приведение к указателю на double

box = &y; // операция взятия адреса переменной y

short* y_ptr = (short*)box; // требуется явное приведение к указателю на short

int* any = ptr; // теперь указатели ptr и any хранят один и тот же адрес в памяти

int* obj = new int; // выделение памяти в куче под переменную типа int

delete obj; // после завершения использования динамической памяти её ресурсы требуется явно освободить

int* vec = new int[var]; // выделение памяти в куче под массив типа int на 5 элементов

delete[] vec; // освобождение ресурсов динамической памяти

int** matrix = new int[var]; // указатель на указатель позволяет выделять память под массив массивов

for (int i = 0; i < var; ++i) matrix[i] = new int[var]; // выделяем память под матрицу 5х5

for (int i = 0; i < var; ++i) delete[] matrix[i]; // удаляем строки матрицы

delete[] matrix; // удаляем указатель на массив массивов

matrix = nullptr; // запрещаем повторное обращение из кода к удалённому объекту.

Выводы:

- указатель – это переменная, которая хранит адрес первого байта объекта в памяти либо nullptr;

- тип указателя совпадает с типом объекта, на который он указывает;

- указатель на void является универсальным так как может хранить адрес объекта произвольного типа, но при его разыменовании требуется явно приводить к типу объекта;

- над указателями допустимы две операции – операция взятия адреса и операция разыменования;

- присвоить указателю указатель – означает создать его копию;

- по указателю можно выделять память в куче под одиночный объект или под массив объектов, ресурсы такой памяти следует освобождать явно;

- указатель на указатель позволяет выделять память под массив массивов, выделение и освобождение памяти под элементы такого массива производится в цикле.
Влад Витковский
Влад Витковский
69 633
Лучший ответ
7 9 > над указателями допустимы две операции – операция взятия адреса и операция разыменования;

Ещё адресная арифметика и [ ]
ну, если на пальцах... вот есть машинная память - пронумерованные ячейки:

1000:
1001:
1002:
1003:
1004:
и т. д.

когда мы объявляем
int a;
мы говорим машине завести переменную a, и машина выделяет под хранение этой переменной какой-то адрес в памяти:

1000: <- тут будет храниться значение переменной a
1001:
1002:
1003:
1004:

пишем a = 23 и получаем:

1000: 23 <- тут хранится значение переменной a
1001:
1002:
1003:
1004:

пусть теперь у нас объявление
int *a;
в памяти пока всё то же:

1000: <- тут будет храниться значение переменной a
1001:
1002:
1003:
1004:

а вот при выполнении команды
a = (int)calloc(1, 1);
происходит маленькое чудо:

1000: 1003 <- тут хранится адрес, на который ссылается a
1001:
1002:
1003: <- тут будет храниться значение, которое примет *a
1004:

поэтому написав
*a = 23;
получим в памяти:

1000: 1003 <- тут хранится значение указателя a
1001:
1002:
1003: 23 <- тут хранится значение, на которое указывает a, т. е., *a
1004:
7 9 a = (int*)calloc(1, 1);
пропущена звёздочка
>> Чем отличается переменная *a от простой a в C++?
Это некорректно построенный вопрос и любой ответ на него будет ошибочным. в вопросе уже есть ошибка которая поломает любую логику если отвечать на него, но если указать на нее то все должно стать на свои места.

--- Похоже без Капитана Очевидности тут не обойтись ---
В данном случае " *a " не является переменной это выражение состоящие из оператора и операнда.
Оператор совершает операции над операндом в результате чего получается результат выражения.
" a " так же является выражением но тут нет операторов по этому результатом выражения будет значение переменной ассоциированное с именем "а" (адрес памяти в виде числа).
В случае выражения " *a " сначала так же берется значение переменной ассоциированное с именем "а "(адрес памяти) а затем над ним проводится операция "операция разыменования указателя" т. е. получение значение переменной ассоциированного типа по указанному адресу.

т. е. в одном случае полученное значение выражения это адрес памяти а в другом это значение переменной находящиеся по адресу.
Смотря где!
тип * a; - это определения указателя
*a - это получение значения переменной на которую указывает указатель a
переменная *a - это умножение переменной на a
Звёздочка стоящая перед именем или после имени типа переменной как int* a или int *a объявляет указатель на объект int. Переменные указатели могут хранить всего три значения 0 NULL и адреса переменных. Если ты знаешь что такое указатели то ты должен понимать разницу между ними, указатели это просто переменные хранящие адреса других переменных, указатели не могут хранить обычные значения как 100 50 12 они могут хранить либо NULL или адрес переменной на которую он указывает. Сам же говоришь что знаешь что такое указатели, если бы знал то такой вопрос бы не задавал, возьми любой учебник по C/С++ открой главу с указателями и освежи себе память. Там с примерами более подробно разжуют.
Сергей Фёдоров На самом деле указатель може хранить только адрес, а то что один из адресов ( 0 или NULL ) зарезервировали для упрощения обработок ошибочных ситуаций - "костыль"