Форум программистов, компьютерный форум CyberForum.ru

Понимание адреса, ссылки и указателя - C++

Восстановить пароль Регистрация
 
 
Рейтинг: Рейтинг темы: голосов - 36, средняя оценка - 4.69
The_Immortal
1548 / 484 / 8
Регистрация: 04.04.2009
Сообщений: 1,891
30.05.2012, 11:31     Понимание адреса, ссылки и указателя #1
Гм... Конечно, стремно создавать подобную тему, однако, уж очень захотелось понять все это дело. Правда сколько раз ни пытался - не удавалось ни разу, возможно, потому что пытался разобраться самостоятельно (хотя, наверное, многие это постигают именно так). Но вот моя очередная попытка, которую решил так сказать обнародовать Поэтому очень рассчитываю на вашу помощь и поддержку.

Итак, начал практически с самого начала и уже сразу же зашел в тупик.
Ниже приведен легенький код, демонстрирующий расположение переменных в памяти компа.

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
// расположение переменных в памяти
#include <cstdio.h>
#include <cstlib.h>
#include <iostream.h>
 
using namespace std;
 
int main(int intArgc, char* pszArgs[])
{
int end;
int n;
long l;
float f;
double d;
 
// Вывод в шестнадцатеричном виде
cout.setf (ios::hex);
cout.unsetf (ios::hex);
 
// выводить адреса переменных
// по очереди, чтобы показать размер
// каждой переменной
cout << "--- = " << &end << "\n";
cout << "&n = " << &n << "\n";
cout << "&l = " << &l << "\n";
cout << "&f = " << &f << "\n";
cout << "&d = " << &d << "\n";
 
system ("PAUSE");
return 0;
}
Результат:

C++
1
2
3
4
5
--- = 0x22ff6c
&n  = 0x22ff68
&l  = 0x22ff64
&f  = 0x22ff60
&d  = 0x22ff58
А теперь цитата из книги:
Обратите внимание на то, что переменная n располагается ровно в 4 байтах от переменной end (---). Переменная l располагается еще на 4 байта ниже, а переменная типа double занимает 8 байт. Для каждой переменной выделяется память, необходимая для ее типа.
Для каждой переменной выделяется память, необходимая для ее типа.
Это мне известно. Но вот что меня занесло в тупик:

Разница, скажем, между 0x22ff6c и 0x22ff68 действительно 4. Но 4 чего - байта? А разве 4 в десятичной системе не 4? А в двоичной это разве не 100? Откуда тут 4 байта? Я понимаю, что там должно быть 4 байта, но не получается осознать, что 1 hex-единица у нас вдруг байт. Или это не так?

В общем, на таком банальном я запутался

Спасайте...
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
30.05.2012, 11:31     Понимание адреса, ссылки и указателя
Посмотрите здесь:

Ссылки и адреса C++
C++ Возвращение ссылки или указателя на закрытый элемент класса.
Написать обработчик исключений ситуации при преобразовании указателя на класс B до указателя на абстрактный класс А ... C++
При передачи указателя на обьект ошибка,а при передаче ссылки на указатель нет. Почему? C++
Функция с возвратом указателя и возвратом ссылки C++
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
dimcoder
Полярный
 Аватар для dimcoder
449 / 422 / 66
Регистрация: 11.09.2011
Сообщений: 1,108
30.05.2012, 12:01     Понимание адреса, ссылки и указателя #2
Цитата Сообщение от The_Immortal Посмотреть сообщение
Но 4 чего - байта?
Да.
Может так нагляднее будет:
--- = 0x22ff6c = 2 293 612
&n = 0x22ff68 = 2 293 608
&l = 0x22ff64 = 2 293 604
&f = 0x22ff60 = 2 293 600
&d = 0x22ff58 = 2 293 592
Вот вам и разница байтов.
The_Immortal
1548 / 484 / 8
Регистрация: 04.04.2009
Сообщений: 1,891
30.05.2012, 12:48  [ТС]     Понимание адреса, ссылки и указателя #3
dimcoder,

Цитата Сообщение от dimcoder Посмотреть сообщение
2 293 612
Это байты?

В смысле 1 (Dec) = 1 байт?
dimcoder
Полярный
 Аватар для dimcoder
449 / 422 / 66
Регистрация: 11.09.2011
Сообщений: 1,108
31.05.2012, 08:37     Понимание адреса, ссылки и указателя #4
Цитата Сообщение от The_Immortal Посмотреть сообщение
Это байты?
Да, байты.
zss
Модератор
Эксперт С++
 Аватар для zss
5944 / 5549 / 1783
Регистрация: 18.12.2011
Сообщений: 14,175
Завершенные тесты: 1
31.05.2012, 11:00     Понимание адреса, ссылки и указателя #5
В теме обсуждается понятие адреса переменной.
А в заголовке еще анонсирована ссылка и указатель.
Вопрос: зачем?

Кстати, сколько байт занимает переменная можно определить с помощью
sizeof(тип):
C++
1
2
int si=sizeof(int);
int sd=sizeof(double);
Deviaphan
Делаю внезапно и красиво
Эксперт C++
 Аватар для Deviaphan
1283 / 1217 / 50
Регистрация: 22.03.2011
Сообщений: 3,744
31.05.2012, 11:05     Понимание адреса, ссылки и указателя #6
Цитата Сообщение от The_Immortal Посмотреть сообщение
Обратите внимание на то, что переменная n располагается ровно в 4 байтах от переменной en
А вот этим строкам лучше не верь. В зависимости от параметров компиляции, может быть изменено не только выравнивание, но и порядок переменных.

Объёмы данных измеряются в байтах и их производных (КБ, МБ, ГБ...), про биты забудь. Биты используются только при передаче данных через сеть. На локальной машине битов нет. Даже используя битовые операции, ты работаешь с байтами.

Вместо &end напиши ((unsigned)&end) и адрес выведется в десятичной системе, чтобы вопросов у тебя не возникало лишних.
The_Immortal
1548 / 484 / 8
Регистрация: 04.04.2009
Сообщений: 1,891
31.05.2012, 11:17  [ТС]     Понимание адреса, ссылки и указателя #7
zss, адрес - неотъемлемая часть указателя и ссылки Но я до них еще дойду, т.к. с этим у меня вообще полная каша.

Ребят, а подскажите, пожалуйста, почему

1) Объявляем переменные в таком порядке:

C++
1
2
3
4
5
int end;
int n;
long l;
float f;
double d;
Компилятор идет сверху-вниз.

А адреса назначаются в обратном:

C++
1
2
3
4
5
--- = 0x22ff6c = 2 293 612
&n  = 0x22ff68 = 2 293 608
&l  = 0x22ff64 = 2 293 604
&f  = 0x22ff60 = 2 293 600
&d  = 0x22ff58 = 2 293 592
Т.е. сначала был присвоен адрес переменной d (... 592), потом f (... 600) и т.д.

2) 0x22ff - это какой-то магический префикс? Почему адрес объявленных переменных всегда (ну может не всегда, но зачастую) начинается именно с него?

Добавлено через 8 минут
Цитата Сообщение от Deviaphan Посмотреть сообщение
Биты используются только при передаче данных через сеть.
Хм... Запомню, спасибо. Просто я всегда считал, что и на локальной машине атомной структурой являются биты.
Toshkarik
 Аватар для Toshkarik
1139 / 856 / 50
Регистрация: 03.08.2011
Сообщений: 2,381
Завершенные тесты: 1
31.05.2012, 11:23     Понимание адреса, ссылки и указателя #8
Deviaphan просто имел ввиду не физическое наличие, а реальное использование, то есть по сути процессор работает с машинным словом, а не с каждым битом в отдельности. По поводу адресов - Вам так же уже сказали, что зависит от реализации компилятора, и что переменные не обязаны идти в каком то порядке и вообще находится рядом.
zss
Модератор
Эксперт С++
 Аватар для zss
5944 / 5549 / 1783
Регистрация: 18.12.2011
Сообщений: 14,175
Завершенные тесты: 1
31.05.2012, 11:28     Понимание адреса, ссылки и указателя #9
Цитата Сообщение от The_Immortal Посмотреть сообщение
А адреса назначаются в обратном:
Потому, что локальные переменные заводятся в стеке.
The_Immortal
1548 / 484 / 8
Регистрация: 04.04.2009
Сообщений: 1,891
31.05.2012, 11:35  [ТС]     Понимание адреса, ссылки и указателя #10
Toshkarik,

Цитата Сообщение от Deviaphan Посмотреть сообщение
В зависимости от параметров компиляции, может быть изменено не только выравнивание, но и порядок переменных.
Цитата Сообщение от Toshkarik Посмотреть сообщение
зависит от реализации компилятора, и что переменные не обязаны идти в каком то порядке и вообще находится радом.
Да, ребят, это я понял.
Также в книге об этом написано:

Стандарт C++ не требует от компилятора последовательного "беспросветного" размещения переменных в памяти. Dev-C++ может разместить переменные в памяти и по-другому.
Но мой Dev-C++ их разместил аналогичным образом:

C++
1
2
3
4
5
--- = 2293620
&n  = 2293616
&l  = 2293612
&f  = 2293608
&d  = 2293600
Я не пытаюсь с вами спорить и утверждать, что на всех Dev-C++ всегда будет такое "беспросветное" размещение переменных.
Просто хочу понять каким образом (в данном локальном случае) действует компилятор. Почему объявление переменных происходит сверху-вниз, а размещение этих переменных снизу вверх?

Разве при объявлении переменной не происходит моментального размещения этой переменной в памяти ну и соответствующего присвоения адреса?

Добавлено через 2 минуты
Цитата Сообщение от zss Посмотреть сообщение
Потому, что локальные переменные заводятся в стеке.
Отлично... В книге почему-то об этом не пишут =/

Пойду гуглить по этому поводу
Deviaphan
Делаю внезапно и красиво
Эксперт C++
 Аватар для Deviaphan
1283 / 1217 / 50
Регистрация: 22.03.2011
Сообщений: 3,744
31.05.2012, 11:41     Понимание адреса, ссылки и указателя #11
Цитата Сообщение от The_Immortal Посмотреть сообщение
А адреса назначаются в обратном
Потому что память в стеке используется начиная с верхних адресов.
Toshkarik
 Аватар для Toshkarik
1139 / 856 / 50
Регистрация: 03.08.2011
Сообщений: 2,381
Завершенные тесты: 1
31.05.2012, 11:41     Понимание адреса, ссылки и указателя #12
Вы можете забегать вперед, так как вопрос о классах памяти может обсуждаться дальше в книги.
Лжец
 Аватар для Лжец
31 / 31 / 3
Регистрация: 13.12.2011
Сообщений: 106
31.05.2012, 11:49     Понимание адреса, ссылки и указателя #13
0x22ff - это какой-то магический префикс? Почему адрес объявленных переменных всегда (ну может не всегда, но зачастую) начинается именно с него?
22ff - это уже адрес. Префикс, если можно так сказать, это 0x (или 0Х) - он означает, что данное число (адрес) выведено в 16-ричной системе счисления. Своего рода подсказка.

Почему объявление переменных происходит сверху-вниз, а размещение этих переменных снизу вверх?
Тебе же уже ответили, данные помещаются в стек. "И последний станет первым".

Разве при объявлении переменной не происходит моментального размещения этой переменной в памяти?
Она помещается на вершину стека, после чего по мере объявления и добавления других переменных в стек, она "смещается" вниз по стеку. Если слово "смещается" смущает (потому что никакого "смещения" не происходит), есть стандартный пример для понимания, это "стопка тарелок": когда ты ее складываешь, то кладешь одну тарелку на другую - примерно так же происходит и в стеке.
The_Immortal
1548 / 484 / 8
Регистрация: 04.04.2009
Сообщений: 1,891
31.05.2012, 12:04  [ТС]     Понимание адреса, ссылки и указателя #14
Toshkarik,

Цитата Сообщение от Toshkarik Посмотреть сообщение
Вы можете забегать вперед, так как вопрос о классах памяти может обсуждаться дальше в книги.
Возможно. Но я пробежался по книге и ничего такого не нашел Правда, наверное, книга моя - "C++ для чайников" вряд ли предусматривает рассмотрение подобных вопросов .


Лжец,

Цитата Сообщение от Лжец Посмотреть сообщение
22ff - это уже адрес
Под "префиксом" я имел как раз-таки начало этого адреса. Про "0x" я в курсе. Интересует почему объявление начинается с "22ff"? Это также зависит от компилятора? Если не трудно, кто-нибудь мог бы выложить какие адреса назначаются локальным переменным такого же типа как у меня в начальном примере (кто НЕ юзает Dev-C++).



Deviaphan,

Цитата Сообщение от Deviaphan Посмотреть сообщение
Потому что память в стеке используется начиная с верхних адресов.
Лжец,

Цитата Сообщение от Лжец Посмотреть сообщение
Она помещается на вершину стека, после чего по мере объявления и добавления других переменных в стек, она "смещается" вниз по стеку.

Мм.. Кажется начинаю понимать. После объявлении переменных в стеке вот такая картина:

d
f
l
n
end
Ну и присвоение адресов происходит сверху-вниз. Таким образом d получает адрес: (... i), f получает адрес: (... i+8) и т.д. // в моем "беспросветном" случае

Я правильно понял?
Deviaphan
Делаю внезапно и красиво
Эксперт C++
 Аватар для Deviaphan
1283 / 1217 / 50
Регистрация: 22.03.2011
Сообщений: 3,744
31.05.2012, 12:14     Понимание адреса, ссылки и указателя #15
Цитата Сообщение от The_Immortal Посмотреть сообщение
Интересует почему объявление начинается с "22ff"?
Просто совпадение. Хотя и есть "предпочтительные" адреса для загрузки модулей, но не стоит об этом думать. Это просто совпадение.)


Цитата Сообщение от The_Immortal Посмотреть сообщение
d получает адрес: (... i), f получает адрес: (... i+8) и т.д.
d помещается по адресу: вершина стека минус sizeof(d). Этот адрес становится новой вершиной
f помещается по адресу: вершина стека - sizeof(f). Этот адрес становится новой вершиной стека.

Здесь под стеком нужно понимать не контейнер, а тупо выделенный блок памяти. Никаких итераторов и операций нету. Т.е. это не std::stack, а системный стек. Всё, что он собой представляет, это указатель на вершину стека.
Лжец
 Аватар для Лжец
31 / 31 / 3
Регистрация: 13.12.2011
Сообщений: 106
31.05.2012, 12:15     Понимание адреса, ссылки и указателя #16
Интересует почему объявление начинается на "22ff"?
Потому что именно этот диапазон адресов в данный момент доступен для работы. Например, у меня адреса сейчас начинаются с 012.

Я правильно понял?
Просто представь, что это тарелки, которые кладутся друг на друга и тогда все должно стать достаточно очевидно Переменная получает адрес, следующая переменная получает адрес "выше" предыдущей, т.е. как бы "накладывается поверх".
Deviaphan
Делаю внезапно и красиво
Эксперт C++
 Аватар для Deviaphan
1283 / 1217 / 50
Регистрация: 22.03.2011
Сообщений: 3,744
31.05.2012, 12:17     Понимание адреса, ссылки и указателя #17
Цитата Сообщение от Лжец Посмотреть сообщение
следующая переменная получает адрес выше предыдущей
С тем лишь исключением, что тарелки подкладываются снизу.
Лжец
 Аватар для Лжец
31 / 31 / 3
Регистрация: 13.12.2011
Сообщений: 106
31.05.2012, 12:20     Понимание адреса, ссылки и указателя #18
Цитата Сообщение от Deviaphan Посмотреть сообщение
С тем лишь исключением, что тарелки подкладываются снизу.
Точно
The_Immortal
1548 / 484 / 8
Регистрация: 04.04.2009
Сообщений: 1,891
31.05.2012, 12:29  [ТС]     Понимание адреса, ссылки и указателя #19
Бррр... Пошел на обдумку, что-то конкретно запутался теперь )))
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
31.05.2012, 12:43     Понимание адреса, ссылки и указателя
Еще ссылки по теме:

Изменение адреса указателя C++
C++ Передача как указателя и как ссылки
Передача ссылки и указателя в функцию C++

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
Deviaphan
Делаю внезапно и красиво
Эксперт C++
 Аватар для Deviaphan
1283 / 1217 / 50
Регистрация: 22.03.2011
Сообщений: 3,744
31.05.2012, 12:43     Понимание адреса, ссылки и указателя #20
Я тут учусь работать в дизайнерской программе MS Paint, поэтому разработал для тебя небольшую схемку, которая поможет разобраться.
Или окончательно запутает...

Понимание адреса, ссылки и указателя
Yandex
Объявления
31.05.2012, 12:43     Понимание адреса, ссылки и указателя
Закрытая тема Создать тему
Опции темы

Текущее время: 15:34. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru