|
Компьютерный форум OSzone.net » Программирование, базы данных и автоматизация действий » Программирование и базы данных » C/C++ - Адреса, адресные операторы |
|
|
C/C++ - Адреса, адресные операторы
|
$AutoITer Сообщения: 446 |
Читаю книгу по С++. Дошел до главы "Первое знакомство с указателями в С++", прочитал, и не понял для чего они нужны? Дальше в книге посмотрел листинги программ и эти операторы там активно используются.
Прошу помощи в объяснении. И во всех ли программах нужно это? |
|
------- Отправлено: 21:04, 20-04-2010 |
Будем жить, Маэстро... Сообщения: 6694
|
Профиль | Сайт | Отправить PM | Цитировать Это делается для экономии памяти, т.к. легче хранить и передавать адрес ячейки в которой хранится число или значение, чем использовать несколько копий этого значения. В простых программах можно и без них.
Ну вот как скажем, у тебя есть пять складов по 100 кв. метров каждый, тебе ведь не будет удобно каждый раз все эти пять складов с содержимым перевозить на машине по городу для торговли? Нет. А проще дать адрес этих складов, написаный на бумажке. |
------- Отправлено: 21:51, 20-04-2010 | #2 |
Для отключения данного рекламного блока вам необходимо зарегистрироваться или войти с учетной записью социальной сети. Если же вы забыли свой пароль на форуме, то воспользуйтесь данной ссылкой для восстановления пароля. |
Необычный Сообщения: 4458
|
Профиль | Сайт | Отправить PM | Цитировать Технически, при вызове процедуры и передачи ей в качестве параметра некой переменной, допустим массива, будет передан весь массив. Если эта процедура рекурсивная, то массив будет передаваться каждый раз при вызове. Соотв потребление памяти будет расти прямо пропорционально числу вызов.
Для небольших величин затраты не существенны. Но если задействован баааальшой массив, то эффективнее, с т.з. быстродействия(меньше передаваемый объем) и экономии памяти(отсутствие необходимости дублирования), передать указатель на этот массив. Указатель говорит, что по такому адресу, в памяти хранится массив необходимых данных. В качестве другого примера, мы можем(с использованием соотв. структур) строить любые структуры. (коломбурчик ![]() Практическим примером может служить создание дерева арифметического выражения и создание каким-то там обходом Польской обратной записи. (как обходить знаю, название не помню ![]() Можно попробовать организовать список, двунаправленный список, стек. |
------- Отправлено: 22:34, 20-04-2010 | #3 |
![]() Пользователь Сообщения: 133
|
Профиль | Сайт | Отправить PM | Цитировать Цитата lxa85:
![]() Цитата lxa85:
![]() ![]() Подскажите пожалуйста как это сделать, желательно с примером ![]() |
||
------- Отправлено: 10:20, 21-04-2010 | #4 |
Необычный Сообщения: 4458
|
Профиль | Сайт | Отправить PM | Цитировать EvgeniyQQQ, я честно сознаюсь в том, что я не знаю С++. И предыдущий пост базируется на знаниях языка Pascal. (Да и то, надо будет в отладчик залезть, уточнить).
Так что извините, примеров не будет ![]() |
|
------- Отправлено: 10:46, 21-04-2010 | #5 |
![]() Старожил Сообщения: 232
|
Профиль | Сайт | Отправить PM | Цитировать Цитата EvgeniyQQQ:
|
|
------- Отправлено: 13:36, 21-04-2010 | #6 |
![]() Пользователь Сообщения: 133
|
Профиль | Сайт | Отправить PM | Цитировать ganselo, спасибо за ответ. Но таким образом мы передаём массив по ссылке, т.е. саму ссылку на массив, а не копию всего массива.
Меня же интересует передача в функцию массива по значению. Что в принципе, на сколько мне известно, не возможно. Цитата EvgeniyQQQ:
![]() Вот код, который подтверждает то, что в приведённом вами способе передаётся массив по ссылке, а не по значению: |
|
------- Отправлено: 15:02, 21-04-2010 | #7 |
ИО Капитана Очевидности Сообщения: 5380
|
Профиль | Отправить PM | Цитировать Medic84,
Цитата Medic84:
При выполнении программ процессор напрямую может работать только с двумя типами данных - это "локальные" и "глобальные" переменные. Для хранения локальных переменных текущей функции в стеке программы выделяется область памяти, где каждая переменная размещается на определённом растоянии (смещении) от вершины стека. Адрес вершины хранится в соответствующем регистре (ячейка памяти) процессора. То есть, допустим пользователь описал в программе переменные "A", "B" и "C" целочисленного типа. Компилятор, при создании машинного кода программы, преобразует имя переменных в записи вида [Стек+16], [Стек+20] и [Стек+24]. Соответственно команда "C = A + B" будет выглядеть, как в ячейку памяти [Стек+24] записать [Стек+16] + [Стек+20]. Глобальные переменные аналогично размещаются в определённой области памяти вне стека, и начальный адрес этой области также известен процессору. Но стек и глобальная область имеют очень небольшой размер. Как же программе использовать остальную область памяти (она же "куча")? Через эти самые "указатели". Сначала в стеке создаётся переменная типа "указатель" - её размер обычно составляет 32 бита (4 байта), реже - 64 (для работы в соответствующем режиме на 64-хразрядных процессорах). Потом, по мере выполнения функции, в этот указатель помещается адрес объекта - порядковый номер первой ячейки памяти. Адрес может быть любым - переменной из используемой области стека (текущей фукнции), переменной старших функций (из которой была вызвана текущая), глобальной переменной. Но чаще всего в указатель записывается адрес объекта, для которого особыми командами в "куче" был выделен участок памяти. Соответственно команда " *pC = A + B" означает "в ячейку памяти по адресу ячейки [Стек+24] записать результат [Стек+16] + [Стек+20]". При работе с указателями в С++ используются две команды - & (получение адреса) и * (обращение по адресу). Конечно, официально они называются иначе, вот только официальные названия звучат очень заумно и совершенно непонятно ![]() *pA = B . Значение переменной B помещается в ячейку памяти, адрес которой содержится в указателе pA pA = &B . Адрес ячейки памяти переменной B записывается в указатель pA (теперь, записывая что-то в *pA, мы изменим значение B) Можно даже так - *pA = *pB - значение ячейки памяти, адрес которой содержится в указателе pB, записывается в ячейку памяти, адрес которой содержится в указателе pA А вот если сделать pA = pB, то оба этих указателя станут указывать на одну и ту же переменную |
|
------- Последний раз редактировалось El Scorpio, 22-04-2010 в 07:51. Отправлено: 06:55, 22-04-2010 | #8 |
ИО Капитана Очевидности Сообщения: 5380
|
Профиль | Отправить PM | Цитировать Зачем это всё вообще надо
1. Для работы с большими объёмами данных То есть, в "куче" создаётся "тяжёлый" объект (например, изображение), а в стеке программа хранит только маленький указатель на этот объект. 2. Чтобы избежать лишнего копирования больших объёмов данных То есть, можно написать функцию как void ShowPicture (TPicture Picture), а можно как void ShowPicture (TPicture *Picture). В первом случае в области стека функции будет создана копия картинки (размером в пару-тройку мегабайт ), а во втором будет передан лишь маленький указатель. Очень актуально для всех программ сложнее "Hello, World!" ![]() 3. Чтобы изменить объект данных в вызываемой функции Если передать в функцию копию объекта, то после выполнения функции стек сократится обратно,*и все внесённые изменения будут утеряны. А*если передать указатель на объект, то функция будет изменять именно этот объект. 4. Чтобы получить несколько результатов в одной функции (частный случай п.3) К примеру, функция SinCos (long double Angle, long double *Sinus, long double *Cosinus) будет записывать синус и косинус угла в ячейки памяти, указатели на которые программист укажет в качестве второго и третьего параметров. Пример вызова - SinCos (Alpha, &SinA, &CosA) Частным случаем указателей являются "ссылки", у которых при объявлении вместо знака * ставится & int A, B; // объявляются две переменные int *pA = &A; // Указатель на переменную А int &rA = A; // ссылка на переменную А rA = B; // Значение B записывается в ячейку памяти по адресу, который содержится в ссылке rA *pA = B; // Значение B записывается в ячейку памяти по адресу, который содержится в указателе pA - при их использовании сразу производится обращение к значению по адресу ссылки (для указателей нужно ставить символ * ) - нельзя переназначить ссылку на другой объект - при объявлении ссылки нужно сразу указывать объект Пример использования ссылки int Array [100]; for (i = 0; i < 100; i++) { int &Item = Array [i]; // а дальше идут 10 строк кода, где используется ссылка Item } Обычно указатели используют для работы с объектами больших размеров (строки, массивы, объекты классов), а ссылки - для объектов поменьше (переменные простых типов, структуры). Просто потому,*что для указателей в отладчике отображаются их адреса, а для ссылок - значения по адресу. |
------- Отправлено: 07:47, 22-04-2010 | #9 |
Ветеран Сообщения: 5624
|
Профиль | Отправить PM | Цитировать El Scorpio, тебе в преподаватели пора по C++
![]() |
------- Отправлено: 07:54, 22-04-2010 | #10 |
|
![]() |
Участник сейчас на форуме |
![]() |
Участник вне форума |
![]() |
Автор темы |
![]() |
Сообщение прикреплено |
| |||||
Название темы | Автор | Информация о форуме | Ответов | Последнее сообщение | |
Мобильные операторы 2.0 | OSZone Software | Новости программного обеспечения | 0 | 04-04-2010 14:30 | |
PowerShell - [блог] Регулярные выражения – Операторы -replace и -split | Xaegr | Скриптовые языки администрирования Windows | 0 | 18-12-2009 19:30 | |
Операторы мобильной связи и тарифы | Ser6720 | Мобильные ОС, смартфоны и планшеты | 17 | 10-09-2009 16:07 | |
Операторы сотовых телефонов! | wolf | Мобильные ОС, смартфоны и планшеты | 71 | 29-05-2004 18:00 | |
Есть ли в России операторы стандарта CDMA? | Yustus | Мобильные ОС, смартфоны и планшеты | 17 | 07-02-2003 09:42 |
|