Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.85/47: Рейтинг темы: голосов - 47, средняя оценка - 4.85
1569 / 505 / 48
Регистрация: 04.04.2009
Сообщений: 1,891

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

30.05.2012, 11:31. Показов 10878. Ответов 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
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
30.05.2012, 11:31
Ответы с готовыми решениями:

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

Вывод адреса указателя
Здравствуйте , ни как не могу вывести адрес указателя Вот прога program Project19; {$APPTYPE CONSOLE} {$R *.res} ...

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

103
 Аватар для Toshkarik
1181 / 894 / 94
Регистрация: 03.08.2011
Сообщений: 2,461
31.05.2012, 14:20
Студворк — интернет-сервис помощи студентам
Да человек вообще чаще всего понимает по своему, что бы там ни было написано.
0
1569 / 505 / 48
Регистрация: 04.04.2009
Сообщений: 1,891
31.05.2012, 15:12  [ТС]
Ух, мужики, ну Вы тут и заварили

В общем, из всего, что я прочел я так и не понял, что такое ссылка.
В смысле вот это
Цитата Сообщение от taras atavin Посмотреть сообщение
Ссылка - это второе имя переменной. Вот тебя как в реале зовут? А здесь тебя зовут The_Immortal. Так сколько у тебя имён? Два уже детектед: то, которое дали при рождении и ещё The_Immortal. У человека второе имя - ник, у переменной - ссылка.
я понимаю. И, кстати, огромное спасибо, что пытаетесь донести подобными примерами - очень ценю это, т.к. действительно помогает.
Но все же без формализации в итоге никак.

У меня просто в голове не укладывается, как две переменные могут сидеть по одному адресу... Или это чисто логический прием?


Цитата Сообщение от taras atavin Посмотреть сообщение
Ссылка может быть пустой
И это также непонятно. Разве может ссылка (по своему назначению должна на что-то ссылаться) указывать на ничто?
Хотя вот указатель же необязательно инициализровать, так? Соответственно он может быть пустым почему-то...

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



Добавлено через 7 минут
Цитата Сообщение от taras atavin Посмотреть сообщение
Ведёт себя, как разыменованный константный указатель
Цитата Сообщение от alkagolik Посмотреть сообщение
ссылка это разыменованный указатель
А это я тоже с трудом понял, примерно вот так (задача корявая, т.к. формулировал сам):
Задача: передать переменной x значение через переменную y, используя:
а) указатель
б) ссылку
а)
C++
1
2
3
4
5
int x;
int *y;
 
y=&x;
*y=5;
б)
C++
1
2
3
4
int x;
int &y=x;
 
y=5;
Вы это имели в виду?
0
 Аватар для Borkot
4 / 4 / 2
Регистрация: 05.05.2012
Сообщений: 201
Записей в блоге: 1
31.05.2012, 15:18
Ссылка как только объявляется сразу инициализируется
типа
C
1
int &p=m;
то есть адрес взятия находится в левом краю,
а вот указатель можно присвоить потом или вообще в (NULL) то есть в ноль.В книгах так написано.
типа
int *p;
C
1
2
3
*p=NULL;
//или просто
*p=0;
0
 Аватар для alkagolik
1599 / 622 / 113
Регистрация: 15.07.2011
Сообщений: 3,548
31.05.2012, 15:24
Цитата Сообщение от The_Immortal Посмотреть сообщение
Вы это имели в виду?
да, лишь забыл уточнить что ссылка есть константный разыменованный указатель. Всегда привязан к одной области (переменной) вот пример
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <iostream>
 
using namespace std;
 
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 = " << x <<  endl;
    s = y;
    cout << *p << ' ' << s << ' ' << y << " x = " << x <<  endl;
 
    return 0;
}
1
1569 / 505 / 48
Регистрация: 04.04.2009
Сообщений: 1,891
31.05.2012, 15:24  [ТС]
Borkot, да, спасибо (жаль "спасибо" мои закончились).

C++
1
*p=0;
Но таким образом сам-то указатель не обнуляется, верно? Это обычное разыменование - т.е. по адресу переменной, на которой указывает этот указатель, записывается 0.
1
 Аватар для Borkot
4 / 4 / 2
Регистрация: 05.05.2012
Сообщений: 201
Записей в блоге: 1
31.05.2012, 15:27
Я почему спросил по поводу указателей
Укзатель
C
1
2
3
4
5
6
7
8
int px,*p;
p=&px//тут указателю *p присваивается адресс &px
//Это понятно
//Но во многих книгах указывается еще такое
*p=&px//причем без **P
//ИЛи оба тождевства верны но толко если?
p=&px;//Либо
*p=px;
Ладно пойду опять читать мануалы пока не пойму.Спасибо за ваши ответы.
0
1569 / 505 / 48
Регистрация: 04.04.2009
Сообщений: 1,891
31.05.2012, 15:32  [ТС]
alkagolik, большое спасибо за пример! Буду разбирать его.


Borkot,
Цитата Сообщение от Borkot Посмотреть сообщение
*p=&px//причем без **P
Да вот это по-моему бред. Что за книга такая?
0
 Аватар для alkagolik
1599 / 622 / 113
Регистрация: 15.07.2011
Сообщений: 3,548
31.05.2012, 15:38
Цитата Сообщение от The_Immortal Посмотреть сообщение
Да вот это по-моему бред. Что за книга такая?
да собственно ничего страшного. Правда этого просто не нужно. В данном случае p хранит адрес px, по которому позже записывает ее же адрес, т.е. значение px равно адресу px. Подвох в том что адреса не имеют отрицательных значений и следовательно представлены беззнаковым типом, а px объявлена как знаковое целое.
1
1569 / 505 / 48
Регистрация: 04.04.2009
Сообщений: 1,891
31.05.2012, 15:44  [ТС]
alkagolik,
Цитата Сообщение от alkagolik Посмотреть сообщение
Подвох в том что адреса не имеют отрицательных значений и следовательно представлены беззнаковым типом, а px объявлена как знаковое целое.
Именно!

То есть тут я был прав?
Цитата Сообщение от The_Immortal Посмотреть сообщение
хм, а тут ты по этому адресу (т.е. переменной p) присваиваешь значение этого адреса что ли
0
Делаю внезапно и красиво
Эксперт С++
 Аватар для Deviaphan
1313 / 1228 / 72
Регистрация: 22.03.2011
Сообщений: 3,744
31.05.2012, 15:47
Цитата Сообщение от The_Immortal Посмотреть сообщение
Да вот это по-моему бред
Ты абсолютно прав. Вариант, когда ты был бы не прав, я чуть выше нарисовал, это когда int **p;
Поэтому шняжные книжки лучше не читать.)

Цитата Сообщение от The_Immortal Посмотреть сообщение
У меня просто в голове не укладывается, как две переменные могут сидеть по одному адресу... Или это чисто логический прием?
Щяс разжую.

есть код
C++
1
2
3
int v = 5; // адрес, допустим 0x0022ff08
int * p = &v; // адрес, допустим 0x0022ff04
int & r = v; // ВНИМАНИЕ , адрес r РАВЕН адресу v, т.е. 0x0022ff08
Т.е. в коде между использованием v и r нет никакой разницы, это одно и то же. Это не две переменные, расположенные по одному адресу, а одна и та же переменная. Ты сразу спросишь, зачем это нужно и я не менее сразу же отвечу кодом

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
struct A
{
    int v;
};
 
A a;
int & r = a.v;
// Теперь вместо a.v = 10 можно написать r = 10
 
 
void Func( int & r )
{
    r = r * r;
}
 
int b = 10;
Func(b);
 int c= b; // c = 100

По указателям.
р расположен по адресу 0x0022ff04 и по этому адресу записан адрес переменной v 0x0022ff08.

Добавлено через 1 минуту
Цитата Сообщение от alkagolik Посмотреть сообщение
В данном случае p хранит адрес px
Только нужно сделать оговорку, что это действительно только для 32 битной системы и, что компилятор будет страшно ругаться.
1
1569 / 505 / 48
Регистрация: 04.04.2009
Сообщений: 1,891
31.05.2012, 16:01  [ТС]
Deviaphan, по первому мини-кодику усе ясно, второй же код мой мозг пока не осилил - чуть позже еще попробую

Цитата Сообщение от Deviaphan Посмотреть сообщение
Ты сразу спросишь, зачем это нужно и я не менее сразу же отвечу кодом
Просто я, если честно, ответа не уловил И с трудом пока понимаю необходимость использования и ссылок и указателей (да и вообще их вместе взятых ). Ведь ссылка - частный случай указателя. Или наоборот...

Ну как бы это разве не равносильно:

C++
1
2
3
4
5
6
7
8
void Func( int r )
{
    r = r * r;
}
 
int b = 10;
Func(b);
 int c= b; // c = 100
?



Вот еще такой вопрос созрел: как можно вывести на экран то, что в данный момент хранит указатель?
К примеру:
C++
1
2
3
4
5
6
7
8
int x;
int *y;
 
y=&x;
 
//пытался так:
cout << "y= " <<&y << "\n"; //но так я получаю адрес, по которому расположен 
//этот указатель, а не то, какой адрес он хранит, т.е. адрес переменной x
0
 Аватар для alkagolik
1599 / 622 / 113
Регистрация: 15.07.2011
Сообщений: 3,548
31.05.2012, 16:08
Deviaphan, да что-то даже без варнингов.
indicator@indicator:~$ cat test.cc
#include <iostream>
#include <iomanip>

using namespace std;
typedef unsigned uint32;

int main() {

uint32 *p , x = 2;
p = &x;
*p = (uint32)&x;

cout << hex << *p << ' ' << &x << ' ' << x << endl;

return 0;
}
indicator@indicator:~$ g++ test.cc
indicator@indicator:~$ ./a.out
bf910e48 0xbf910e48 bf910e48
0
1569 / 505 / 48
Регистрация: 04.04.2009
Сообщений: 1,891
31.05.2012, 16:13  [ТС]
alkagolik, у меня ругается:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <cstdlib>
#include <iostream>
 
using namespace std;
 
int main(int intArgc, char* pszArgs[])
{
int end;
int * pntr;
*pntr=&end; // main.cpp invalid conversion from `int*' to `int' 
 
system ("PAUSE");
return 0;
}
0
Делаю внезапно и красиво
Эксперт С++
 Аватар для Deviaphan
1313 / 1228 / 72
Регистрация: 22.03.2011
Сообщений: 3,744
31.05.2012, 16:15
Цитата Сообщение от alkagolik Посмотреть сообщение
да что-то даже без варнингов
В исходной задаче используются указатели на знаковый int. То что без ворнингов, это косяк компилятора. Попробуй х64 версию собрать и будут тебе ворнинги. И не правильно работающая программа.

Добавлено через 50 секунд
Цитата Сообщение от alkagolik Посмотреть сообщение
*p = (uint32)&x;
И вообще, ты явное преобразование сделал. По условию вопроса там неявное преобразование.
0
1569 / 505 / 48
Регистрация: 04.04.2009
Сообщений: 1,891
31.05.2012, 16:16  [ТС]
С uint32 тоже ругается:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <cstdlib>
#include <iostream>
 
using namespace std;
typedef unsigned uint32;
 
int main(int intArgc, char* pszArgs[])
{
uint32 end=5;
uint32 * pntr;
*pntr=&end; // main.cpp invalid conversion from `uint32*' to `unsigned int' 
 
system ("PAUSE");
return 0;
}
0
 Аватар для alkagolik
1599 / 622 / 113
Регистрация: 15.07.2011
Сообщений: 3,548
31.05.2012, 16:17
The_Immortal, конечно ругается. у тебя изначально указатель указывает в неизвестность, хранит в себе мусор. ты его проинициализируй каким - то адресом, а уж потом используй. Ты пытаешься разыменовать мусор.

Добавлено через 59 секунд
Deviaphan, конечно. без преобразования и не скомпиляется. Грязные методы.
0
1569 / 505 / 48
Регистрация: 04.04.2009
Сообщений: 1,891
31.05.2012, 16:19  [ТС]
Цитата Сообщение от Deviaphan Посмотреть сообщение
И вообще, ты явное преобразование сделал. По условию вопроса там неявное преобразование.
Да, с явным ничего не говорит (не ругается), но прога у меня вылетает при запуске.

Добавлено через 58 секунд
alkagolik,
Цитата Сообщение от alkagolik Посмотреть сообщение
ты его проинициализируй каким - то адресом
Сделал
0
Делаю внезапно и красиво
Эксперт С++
 Аватар для Deviaphan
1313 / 1228 / 72
Регистрация: 22.03.2011
Сообщений: 3,744
31.05.2012, 16:19
Цитата Сообщение от The_Immortal Посмотреть сообщение
Ну как бы это разве не равносильно:
Нет. Результатом твоего примера r не изменится.


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


Цитата Сообщение от The_Immortal Посмотреть сообщение
Ведь ссылка - частный случай указателя. Или наоборот...
Между ними нет ничего общего. Это тебя запутали фразами типа "разыменованный указатель".

Фактически, основная разница в том, что ссылку нужно инициализировать при создании. Т.е. вместо указателя ты можешь написать 0, а вот с ссылкой это не пройдёт. А что использовать, ссылку или указатель, это уже дело вкуса. О тонкостях, связанных с оптимизацией кода, лучше не волнуйся.
0
1569 / 505 / 48
Регистрация: 04.04.2009
Сообщений: 1,891
31.05.2012, 16:20  [ТС]
Цитата Сообщение от The_Immortal Посмотреть сообщение
Вот еще такой вопрос созрел: как можно вывести на экран то, что в данный момент хранит указатель?
Ребят, так а это как сделать?
0
 Аватар для alkagolik
1599 / 622 / 113
Регистрация: 15.07.2011
Сообщений: 3,548
31.05.2012, 16:26
Цитата Сообщение от The_Immortal Посмотреть сообщение
С uint32 тоже ругается:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <cstdlib>
#include <iostream>
 
using namespace std;
typedef unsigned uint32;
 
int main(int intArgc, char* pszArgs[])
{
uint32 end=5;
uint32 * pntr = &end; /************************* тут я дописал **************************/
*pntr=&end; // main.cpp invalid conversion from `uint32*' to `unsigned int' 
 
system ("PAUSE");
return 0;
}
5 букв

Добавлено через 1 минуту
Цитата Сообщение от 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;
}
Добавлено через 3 минуты
Цитата Сообщение от Deviaphan Посмотреть сообщение
Между ними нет ничего общего. Это тебя запутали фразами типа "разыменованный указатель".
разве? а не так?
int &x == int* const point;
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
31.05.2012, 16:26

Как сохранить значение адреса указателя в обычную переменную?
Всем привет. Пишу лабиринт на C++. С языком знаком мало. В общем, я в курсе, что можно в функцию передавать аргументы как pointer и как...

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

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

выделение памяти при увеличении адреса указателя на размерность int
добрый день, форум изучаю указатели и столкнулся с достаточно странной, для меня проблемой int в c++, как я учил, имеет стандартную...

Отличие ссылки от указателя
Здравствуйте. Не совсем понимаю отличие ссылки от указателя. В частности, при передаче результата в функции. Например, попытаюсь...


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

Или воспользуйтесь поиском по форуму:
60
Закрытая тема Создать тему
Новые блоги и статьи
Оказывается, Unreal Engine позволяет качество на порядки выше, чем было в Lineedge
Etyuhibosecyu 05.07.2026
Жаль, конечно, что я не узнал об этом, пока Lineedge существовала, а то бы Noname2331 написал, что волки превращаются в пиксельную кашу, а я бы его попросил скачать какую-нибудь бриллиантовую или Pro. . .
Doom для терминала без стрельбы и монстров. 3D Raycasting на ascii.
dcc0 05.07.2026
Попросил нейронную сеть deepai. org написать рейкастинг 3D с библиотекой ncurses для Linux. Чтобы можно было ходить на стрелочки. Чтобы стены были отрисованы символами. Справилась. Первый вариант. . .
Установка статуса документа по условию
Maks 05.07.2026
Алгоритм из решения ниже реализован на нетиповом документе "НарядПутевка" разработанного в КА2. Задача: в табличной части "Материалы" документа при записи автоматически устанавливать статус. . .
Сезонность и суточность закисления почв
anaschu 04.07.2026
200 часов это все равно моловато. Есть ситуации, но нестандартные, когда смена происходит за 5 лет. Но обычно это 50 лет и более. Наверное, закисление почвы происходит сезонно в средней. . .
В чем ценность человеческого опыта в глобальном смысле?
kumehtar 03.07.2026
Возможно, ценность человека не в том, что он однажды достигает мудрости, а в том, что он становится носителем карты пути. Он знает не только истину, но и последовательность внутренних изменений,. . .
интеграция AnyLogic с самописным REST API и переход на Odoo
anaschu 03.07.2026
Успешная интеграция AnyLogic с самописным REST API и переход на промышленную Odoo WMS Сегодня проделал огромный путь от простой симуляции физических процессов до построения полноценной. . .
Поиск всех путей на ориентированном графе. Linux
dcc0 02.07.2026
Переработка старого кода из моей статьи. Через несколько переработок от PHP кода к C89 (надеюсь, 89). Но довольно запутанно получилось. Код для Linux. Но если убрать time и то, что с ним. . .
Сам себя обучал rest api
anaschu 02.07.2026
Педагогический лайфхак: Почему чистый REST API для ученика намного круче, чем готовые библиотеки Когда мы отказались от капризного JAR-файла AnyLogic и переписали код на стандартный HttpClient,. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru