Форум программистов, компьютерный форум, киберфорум
Наши страницы
С++ для начинающих
Войти
Регистрация
Восстановить пароль
 
 
Рейтинг 4.97/29: Рейтинг темы: голосов - 29, средняя оценка - 4.97
The_Immortal
1560 / 496 / 48
Регистрация: 04.04.2009
Сообщений: 1,891
1

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

30.05.2012, 11:31. Просмотров 5220. Ответов 103
Метки нет (Все метки)

Гм... Конечно, стремно создавать подобную тему, однако, уж очень захотелось понять все это дело. Правда сколько раз ни пытался - не удавалось ни разу, возможно, потому что пытался разобраться самостоятельно (хотя, наверное, многие это постигают именно так). Но вот моя очередная попытка, которую решил так сказать обнародовать Поэтому очень рассчитываю на вашу помощь и поддержку.

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

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-единица у нас вдруг байт. Или это не так?

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

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

Изменение адреса указателя
Здравствуйте. Обращаюсь к форуму по следующему вопросу: как можно изменить...

Динамическое указание адреса указателя
мне нужно сделать int * a=(int*)0x123ff; cout&lt;&lt;a; динамически. Кто...

Использование ссылки и указателя
Доброго времени суток! Возник такой вопрос, есть код: #include &lt;iostream&gt;...

Получение адреса объекта после обнуления указателя на этот объект
Добрый вечер уважаемые программисты. Интересует следующий вопрос. Есть ли...

Передача ссылки и указателя в функцию
передал ссылку в одну функцию - нормально, передал в другую - выводит неверное...

103
The_Immortal
1560 / 496 / 48
Регистрация: 04.04.2009
Сообщений: 1,891
31.05.2012, 16:27  [ТС] 61
Deviaphan,
alkagolik,

Цитата Сообщение от Deviaphan Посмотреть сообщение
Так же, как и присвоить ему значение. cout << *у.
Боюсь, вы меня не поняли... Таким образом я получу содержимое переменной по адресу, который хранит в себе указатель.

Т.е. в данном случае:

C++
1
2
3
4
5
6
7
8
9
int main() {
 
    int *p , x = 2;
    p = &x;
 
    cout << "p = " << *p << endl;
    
    return 0;
}
Я получу:
p = 2
.
А мне надо получить:
p = 0x22ff56
, где 0x22ff56 - адрес переменной x.
0
alkagolik
Заблокирован
31.05.2012, 16:28 62
Цитата Сообщение от The_Immortal Посмотреть сообщение
А мне надо получить:
C++
1
2
3
4
5
6
7
8
9
int main() {
 
    uint32 *p , x = 2;
    p = &x;
 
    cout << p << ' ' << *p << endl;
    
    return 0;
}
0
Deviaphan
Делаю внезапно и красиво
Эксперт С++
1306 / 1221 / 72
Регистрация: 22.03.2011
Сообщений: 3,744
31.05.2012, 16:38 63
Цитата Сообщение от The_Immortal Посмотреть сообщение
Боюсь, вы меня не поняли...
int x;
int * p = &x;

cout << &p; // адрес указателя p
cout << p; //адрес переменной, на которую указывает p. Равен &x
cout << *p; // Значение х

Добавлено через 47 секунд
Цитата Сообщение от alkagolik Посмотреть сообщение
разве? а не так?
int &x == int* const point;
Прям вот вообще не так.

Добавлено через 22 секунды
Цитата Сообщение от alkagolik Посмотреть сообщение
разве? а не так?
int &x == int* const point;
Прям вот вообще не так.
0
The_Immortal
1560 / 496 / 48
Регистрация: 04.04.2009
Сообщений: 1,891
31.05.2012, 16:39  [ТС] 64
alkagolik, прошу простить, ступил дважды Значит надо просто выводить без всего.

Хм, а вот таким образом:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
int main() {
 
 //   uint32 *p , x = 2;
  //  p = &x;
 
 int x=2;
 int *p;
 
  cout << p << endl;
    
    system ("pause");
    return 0;
    
}
Сейчас p хранит какой-то рандомный адрес из памяти, так?

Хм, а вот так вот:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
int main() {
 
 //   uint32 *p , x = 2;
  //  p = &x;
 
 int x=2;
 int *p;
 
    cout << &x << endl;
  //  cout << p << ' ' << *p << endl;
        cout << p << ' ' << *p << endl;
    
    system ("pause");
    return 0;
    
}
Вылетает ошибка. Это потому, что по тому рандомному адресу не существует никакого значения или как это понять?
0
alkagolik
Заблокирован
31.05.2012, 16:44 65
Цитата Сообщение от The_Immortal Посмотреть сообщение
Вылетает ошибка. Это потому, что по тому рандомному адресу не существует никакого значения или как это понять?
это понимай так что твоя программа пытается получить доступ к памяти, которая ей запрещена.
Цитата Сообщение от Deviaphan Посмотреть сообщение
Прям вот вообще не так.
но постой, а как же?
0
Deviaphan
Делаю внезапно и красиво
Эксперт С++
1306 / 1221 / 72
Регистрация: 22.03.2011
Сообщений: 3,744
31.05.2012, 16:55 66
Цитата Сообщение от alkagolik Посмотреть сообщение
но постой, а как же?
Читай манул. У ссылки и указателя вообще ничего общего нет.
int &x = v;;
int* const point = &v;
&x == point
но не
int &x == int* const point;
0
taras atavin
4205 / 1768 / 211
Регистрация: 24.11.2009
Сообщений: 27,565
31.05.2012, 17:07 67
Цитата Сообщение от The_Immortal Посмотреть сообщение
C++
1
2
3
4
int main() {
int x=2;
int *p;
cout << p << endl;
Так ты выведешь значение самого указателя, оно же адрес переменной, на которую он указывает.

Добавлено через 1 минуту
Цитата Сообщение от The_Immortal Посмотреть сообщение
Сейчас p хранит какой-то рандомный адрес из памяти, так?
Да. Вполне возможно, что не валидный, то есть переменная по такому адресу может и не существовать.

Добавлено через 1 минуту
Цитата Сообщение от The_Immortal Посмотреть сообщение
Вылетает ошибка. Это потому, что по тому рандомному адресу не существует никакого значения или как это понять?
Значение там может и валяться, такое же мусорное, а нет права доступа по такому адресу.
0
The_Immortal
1560 / 496 / 48
Регистрация: 04.04.2009
Сообщений: 1,891
31.05.2012, 17:11  [ТС] 68
taras atavin, ой, Вы вернулись!

Спасибо большое, я все понял.

Но очень сильно хотел у Вас узнать, что все-таки имелось в виду под
Цитата Сообщение от taras atavin Посмотреть сообщение
Ссылка может быть пустой
Не могли бы пояснить, пожалуйста?
0
taras atavin
4205 / 1768 / 211
Регистрация: 24.11.2009
Сообщений: 27,565
31.05.2012, 17:15 69
Цитата Сообщение от alkagolik Посмотреть сообщение
но постой, а как же?
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
int x; // Переменная
int &s=x; // Ссылка
int *const p=&x; // Указатель
/*Следующие строки эквивалентны:*/
x=2;
s=2;
*p=2;
/*А теперь выводим адреса и ничему не удивляемся*/
cout<<&x<<endl; // Адрес, по которому валяется сама переменная
cout<<&s<<endl; // Адрес, по которому валяется ссылка
cout<<&p<<endl; // Адрес, по которому валяется указатель
/*Указатель валяется по отдельному адресу. А ссылка и переменная?*/
/*Теперь выводим значения*/
cout<<x<<endl; // Значение переменной
cout<<s<<endl; // Значение ссылки
cout<<p<<endl; // Значение указателя
/*А теперь значение по адресу, равному значению указателю*/
cout<<*p<<endl; // Значение переменной
Добавлено через 1 минуту
Цитата Сообщение от The_Immortal Посмотреть сообщение
Не могли бы пояснить, пожалуйста?
Пустая ссылка ни куда не ссылается, она вообще не валидна, но существовать может.
0
The_Immortal
1560 / 496 / 48
Регистрация: 04.04.2009
Сообщений: 1,891
31.05.2012, 17:39  [ТС] 70
Сейчас пытаюсь разобрать пример от alkagolik:


C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
int main() {
 
    int *p, x, y;
    int &s = x;
    p = &x;
 
    *p = 3; // *p - разыменовывание указателя
    cout << *p << ' ' << s << ' ' << x << endl;
    s = 4;
    cout << *p << ' ' << s << ' ' << x << endl;
    p = &y;
    s = y; // y не проинициализирована, теперь x = y т.к. s всегда указывает на x  и только
    *p = 5;
    cout << *p << ' ' << s << ' ' << y << x <<  endl; // вот тут застрял.
    //если честно, то ожидал увидеть: "5 5 5 5", а увидел "5 2293672 5 2293672 "
    s = y;
    cout << *p << ' ' << s << ' ' << y << x <<  endl;
 
    return 0;
}
Так вот, не могу понять почему:
//если честно, то ожидал увидеть: "5 5 5 5", а увидел "5 2293672 5 2293672 "


y не проинициализирована
Согласен. На тот момент да. Но после этого:
C++
1
*p = 5;
инициализация произошла и y=5, разве нет? Соответственно s (как и x) тоже должны быть равны значению y, а не ее адресу... А получилось не так

И только после повторного присвоения
C++
1
    s = y;
Все стало нормально...

Вот этого не понимаю

Добавлено через 9 минут
Соответственно s (как и x) тоже должны быть равны значению y, а не ее адресу...
Ммм... Адрес переменной y тут не причем. Ступил здесь. Просто какое-то рандомное значение выделенное при присвоении.
0
alkagolik
Заблокирован
31.05.2012, 17:42 71
taras atavin, в твоем примере 11 строка некорректна. верно так
C++
1
cout << &(*p) << endl;
это все частности. Конечно "int &x == int* const p" это "грубый" пример, фактически х есть дубликат, а *р - оригинал.
0
Toshkarik
1150 / 867 / 90
Регистрация: 03.08.2011
Сообщений: 2,404
Завершенные тесты: 1
31.05.2012, 17:43 72
Вы 'y' присваиваете ссылке 's' до того как присваиваете ей значение 5. То есть вы сначала присваиваете мусор из 'y' переменной 'x'. И только потом переменной 'y' присваиваете значение 5.
0
alkagolik
Заблокирован
31.05.2012, 17:45 73
The_Immortal, просто s указывает на х и в строке 12 мы присваиваем х = y, но т.к. y = мусор, то и в х записывается мусор.
0
taras atavin
4205 / 1768 / 211
Регистрация: 24.11.2009
Сообщений: 27,565
31.05.2012, 17:50 74
Цитата Сообщение от alkagolik Посмотреть сообщение
cout << &(*p) << endl;
Нет, адреса значения не существует.
0
The_Immortal
1560 / 496 / 48
Регистрация: 04.04.2009
Сообщений: 1,891
31.05.2012, 17:51  [ТС] 75
Toshkarik,
alkagolik,
То, что х = y, т.к. s = y - я понимаю.
Также понимаю, что т.к. y - содержит мусор и соответственно x и s содержат этот мусор я также осознаю.

НО я же
Цитата Сообщение от Toshkarik Посмотреть сообщение
потом переменной 'y' присваиваете значение 5.
правильно? Так почему мусор этот не перезаписывается?
0
taras atavin
4205 / 1768 / 211
Регистрация: 24.11.2009
Сообщений: 27,565
31.05.2012, 17:51 76
И читай:
Цитата Сообщение от taras atavin Посмотреть сообщение
Адрес, по которому валяется указатель
. Сам указатель, а не переменная x.
0
The_Immortal
1560 / 496 / 48
Регистрация: 04.04.2009
Сообщений: 1,891
31.05.2012, 17:53  [ТС] 77
Цитата Сообщение от The_Immortal Посмотреть сообщение
Так почему мусор этот не перезаписывается?
Вот блин, уже на ерунде какой-то застреваю. Все понял, спасибо ребят!


Цитата Сообщение от taras atavin Посмотреть сообщение
Нет, адреса значения не существует.
Хм... А вот это интересно.
0
taras atavin
4205 / 1768 / 211
Регистрация: 24.11.2009
Сообщений: 27,565
31.05.2012, 17:56 78
Как двойному указателю будешь присваивать значение?
C++
1
2
3
int x=2;
int *p=&x;
int **pp=&(*p);
? Не правильно. Правильно просто
C++
1
2
3
int x=2;
int *p=&x;
int **pp=&p;
. А значение указателя - это адрес.

Добавлено через 1 минуту
Цитата Сообщение от The_Immortal Посмотреть сообщение
Хм... А вот это интересно.
C++
1
2
3
4
5
int x;
int *p;
x=5; // x и равен 5
p=&x; // правильно
p=&5; // не правильно: хоть x и равно 5, но 5 адреса не имеет.
0
alkagolik
Заблокирован
31.05.2012, 17:58 79
Цитата Сообщение от The_Immortal Посмотреть сообщение
Хм... А вот это интересно.
не ведись, он сам не понял что написал. Ссылка есть разыменованный константный указатель, т.е. сам указатель и хранить в программе не надо пойми. Создается просто дубликат переменной.

Добавлено через 2 минуты
taras atavin, разбирай
Bash
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
indicator@indicator:~$ cat test.cc
#include <iostream>
 
using namespace std;
typedef unsigned uint32;
 
int main() {
 
    int x = 9;
    int* const p = &x;
    int &s = x;
 
    cout << &(*p) << '\n' << &x << '\n' << &s << endl;
 
    return 0;
}
indicator@indicator:~$ g++ test.cc
indicator@indicator:~$ ./a.out 
0xbf921dd4
0xbf921dd4
0xbf921dd4
indicator@indicator:~$
0
taras atavin
4205 / 1768 / 211
Регистрация: 24.11.2009
Сообщений: 27,565
31.05.2012, 17:58 80
Значения не имеют индивидуальности, а значит и адресов.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
int x;
int y;
int *p;
x=5;
y=5;
p=&5; // адрес какой из пятёрок надо поместить в указатель?
/*То есть какая из переменных должна удвоиться следующей сточкой?*/
*p=*p*2;
if (x<y) // Какой символ надо вывести?
{
 cout<<"x";
}
else
{
 cout<<"y";
}
0
31.05.2012, 17:58
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
31.05.2012, 17:58

Возвращение ссылки или указателя на закрытый элемент класса.
Всех уважаемых форуман. поздравляю с наступившим новым годом и прошу ответить...

Ссылки и адреса
Вот, где лучше всего использовать адреса и ссылки? Просто не много не понятня...

Адресное пространство, адреса, ссылки
Добрый вечер. Я новичок в программировании и стал недавно читать туториалы по...


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

Или воспользуйтесь поиском по форуму:
80
Закрытая тема Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru