| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > C/C++: Общие вопросы > Указатели |
| Автор: Fritz 20.3.2004, 11:55 |
| Люди помогите разобраться с указателями, зачем они ВООБЩЕ нужны а? |
| Автор: Mal Hack 20.3.2004, 21:22 |
| Указатель сразу дает адрес ячейки в памяти, где находтся информация, а при использовании переменных сначала ищется в памяти имя переменной, а потом тот самый адрес. Указатели используются в основном для работы с динамически изменяемыми массивами или в программах, где нужно постоянно чистить память из-за большого количества перебираемых данных. Плюс - это выходя для передачи или возврата неограниченного числа параметров в функцию, массива, короче... |
| Автор: bilbobagginz 20.3.2004, 22:28 |
| кроме вышесказанного: один из самых важных преимуществ указателей это, что они позволяют передавать данные по адресу а не по значению: напр. если у нас есть массив с 10^10 ячеек, то можно просто передать его адрес в функцию, и не надо всю информацию перекачивать на каждый вызов этой функции. |
| Автор: mr.DUDA 20.3.2004, 22:40 |
| И ко всему прочему, могу добавить кучу своих комментариев в теме с таким же названием, находящейся в форуме чуть ниже |
| Автор: Guest 21.3.2004, 02:48 |
| oops |
| Автор: necrom 4.8.2011, 20:17 | ||||||||
Подскажите по указателям вот такую тему.
Почему в первом случае, будет 2
А во втором, 6
И почему данный пример не будет работать при таком раскладе.
Как я понял, здесь идёт приведения типа к указателю (int*), но вот дальше не понятки ( |
| Автор: azesmcar 4.8.2011, 20:55 |
| necrom Да уж, ник у тебя соответствует дате поднятой темы ты сам эту двойку присвоил, а постфиксный оператор ++ возвращает предыдущее значение. потому что так работает арифметика указателей, + 1 на указателе прибавляет указателю число, равное размеру типа указателя, т.е. в данном случае размеру типа int, т.е. 4. Потому что ты пытаешься получить объект int, находящийся по адресу 2, а кто сказал, что этот адрес принадлежит тебе? |
| Автор: necrom 4.8.2011, 21:45 |
| А если читать дословно данную строчку int *iptrs= (int*) 2; то это будет так: Указателю iptrs присвоить адрес памяти в котором записано 2? А как ещё данную запись прочитать 0[&iptrs]? Нулевой элемент массива по данному адресу? |
| Автор: volatile 4.8.2011, 23:56 | ||
не совсем. Указателю iptrs присвоить адрес памяти равной 2. т.е сам адрес равен 2. Походу, это явно системная память. к тому же он не выравнен, а значит щаз придет сыроежка, и опять задолбает, что это вообще не адрес 0[&iptrs] это аналог записи &iptrs[0] то есть это абсолютные синонимы. Означает адрес самого первого элемента массива. |
| Автор: necrom 5.8.2011, 02:15 | ||||
| Фух вроде разобрался, спасибо. Ещё вот такой, надеюсь последний вопрос.
Опять же, как правильно прочитать. И почему ошибка при записи? Переменной ptr типа указателя, на указатель, на указатель типа int выделяется массив памяти из 50 элементов указателей, на указатель типа int. Записываем адрес в указатель, на указатель. Ошибка при записи потому, что не выделена память для указателя?
|
| Автор: volatile 5.8.2011, 12:03 |
| Вы выделили массив int **[50], и не проинициализировали ни один из членов массива. **ptr = &da; // здесь в левой части вы разименовываете первый элемент, а это указатель, который непроинициализирован. нужно как-то так int ***ptr=new int **[50]; // выделили массив 50 указ.на указ int * my_pointer; // какой-то отдельный указатель ptr[0] = &my_pointer; // инициализруем первый элемент выделенного массива. *ptr[0] = &da; // ну вот теперь можно. **ptr = &da; // это синоним предыдущ. строки. my_pointer = &da; // это то, что фактически происходит в этой строке Короче говоря, прежде чем разименовывать указатель, нужно его проинициализировать. Иначе вы обращаетесь по случайному адресу - мусору. А вообще не заморачивайтесь с глубоко вложенными указателями, больше двух ** очень редко когда нужно. |
| Автор: necrom 5.8.2011, 18:09 | ||||
Аргх
my_pointer указывает же тоже на мусор. Мы берём адресс указателя указывающий на мусор и записываем в указатель ptr. А, если рассматривать, то что будет творится в памяти. Предположим у нас есть адреса 0x1000 - 0x1032, то эти указатели будут выглядеть так? И когда мы будем инициализировать первый элемент массива мы запишем 0xFFF (предполагая, что 0xFFF это адрес указателя my_pointer)
|
| Автор: volatile 5.8.2011, 23:21 | ||||
да, в данной точке значение my_pointer есть мусор, но мы его значение не используем. Мы берем адрес my_pointer , а он точно определен, и записываем этот адрес в 0-ой элемент массива. Остальные 49 элементов в данном коде пока не проинициализированы. |
| Автор: volatile 5.8.2011, 23:58 | ||||
да. все верно! У нас массив указателей на указатели. То есть в каждый элемент нужно записать адрес какого-то указателя. И пока мы не запишем, разыменовывать элементы нельзя. В 0-ой элемент мы записали адрес указателя, поэтому можно его разыменовать. в ptr[0] хранится адрес my_pointer, следовательно *ptr[0] - это и есть my_pointer,
а остальные 49 элементов не инициализированы, и например в ptr[1], или ptr[2], хранится мусор, так как мы их не инициализировали пока, следовательно *ptr[1] - это есть разыменование не иницилизированного указателя, т.е указателя указывающего неизвестно куда. и будет ошибка. Не понятно что вам не понятно. |
| Автор: necrom 6.8.2011, 01:06 | ||
| Кажись понял Последний вопрос
Чтоб удалить зарезервированную память нужно написать delete **a; |
| Автор: volatile 6.8.2011, 01:26 |
| До этого нужно примерно таким же циклом, но в обратной последовательности удалить все вложенные массивы. В общем на каждый new []; => свой delete []; delete [] a; |
| Автор: aleks88 3.10.2011, 17:39 | ||
В чем ошибка в перегрузке оператора ? При запуске зависает... Когда в качестве переменного-члена класса использую целочисленную переменную, а не указатель, все норм. Тогда правда и перегрузка оператора иная... |
| Автор: bsa 3.10.2011, 23:11 | ||||
| aleks88, во-первых, где delete в деструкторе? Кстати, конструктор можно упростить: pVal = new int(0); во-вторых, необходим конструктор копирования - без него return temp делать нельзя (ошибка вылезет, как только ты в деструктор добавишь delete). в-третьих, вот эту "порнографию":
в-четвертых, сигнатура префиксного оператора ++ должна быть такой: Counter& operator++(); Почему зависает я не знаю. По идее в данном виде должно работать, но с утечками памяти (ты теряешь три участка памяти). |