С наступающим Новым годом! Форум программистов, компьютерный форум, киберфорум
Наши страницы
С++ для начинающих
Войти
Регистрация
Восстановить пароль
 
 
Рейтинг 4.79/33: Рейтинг темы: голосов - 33, средняя оценка - 4.79
gomodril
6 / 6 / 0
Регистрация: 10.10.2012
Сообщений: 140
1

Расскажите популярно про ссылки и указатели

04.01.2013, 16:05. Просмотров 6094. Ответов 110
Метки нет (Все метки)

Помогите разобраться со ссылками и указателями на различные объекты. Запутался вообще в них полностью. Когда читаю книгу про них, то вроде все понятно написано, но примеров для меня видимо не достаточно, что бы как то их различать. В итоге начинаю решать задачи и ни чего не выходит.
0
Лучшие ответы (1)
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
04.01.2013, 16:05
Ответы с готовыми решениями:

Популярно объясните про указатели
Что-то плохо даётся мне тема про указатели. Я хорошо уяснил, что вот так...

Пояснить про указатели и ссылки
есть переменное и указатель.. Значение нашей переменной случайный адрес, Как...

Подскажите хорошую статью про указатели и ссылки
Посоветуйте статью, видео или книгу по указателям и ссылкам в C++, где все...

Что нужно знать про указатели и ссылки?
Привет, завтра кр по теме указатели и ссылки в с++, пишите сюда что необходимо...

Расскажите про new и delete в C++
Есть несколько вопросов: 1) Можно ли перегрузить несколько операторов new в...

110
Nick Alte
Эксперт С++
1648 / 1020 / 174
Регистрация: 27.09.2009
Сообщений: 1,945
Завершенные тесты: 1
04.01.2013, 16:23 2
Указатель содержит в себе адрес некоего объекта и не стесняется этого. Для обращения непосредственно к объекту используется разыменование (*), адрес в указателе можно заменить на другой. То, что тип - указатель, обозначается звёздочкой (заметим, при обозначении типов и создании переменных у звёздочки смысл именно "указатель", а вот при использовании уже готовых указателей, её смысл - разыменование).
Ссылка "маскируется" под какой-то конкретный объект. Доступ к объекту по ссылке происходит так же, как если бы это был сам объект, "перенастроить" ссылку на другой объект нельзя, поэтому она всегда гарантированно ссылается на один и тот же объект, что часто помогает оптимизации. То, что тип - ссылка, обозначается символом & в составе типа (при использовании с готовыми переменными символ & имеет смысл взятия адреса, такой адрес как раз и можно залить в соответствующий указатель).
Это так, общая ориентировка для начала... Дальше уже по конкретным вопросам
1
gomodril
6 / 6 / 0
Регистрация: 10.10.2012
Сообщений: 140
04.01.2013, 17:00  [ТС] 3
Хорошо, тогда к примеру указатель на символ я правильно объявляю?

char si = 'H';
int si_1 = (int&) si;

В этом случае в si_1 будет адрес переменной si. А если я сделаю как в книжке написано:

char si = 'H';
char * si_1 = & si;

то в переменной si_1 будет HMMM. Вот я и стал путаться.
0
coloc
погромист
412 / 248 / 30
Регистрация: 27.08.2012
Сообщений: 550
Завершенные тесты: 1
04.01.2013, 17:05 4
C++
1
2
3
char s = 'H';
char* ps = &s;
cout << *ps;
В переменной si_1 будет адрес si, а не символы
0
gomodril
6 / 6 / 0
Регистрация: 10.10.2012
Сообщений: 140
04.01.2013, 17:08  [ТС] 5
Цитата Сообщение от coloc Посмотреть сообщение
C++
1
2
3
char s = 'H';
char* ps = &s;
cout << *ps;
В этом случае будет выведена Н, тогда смысл вообще от этих ссылок и указателей, если можно просто вывести значение переменной s...
0
coloc
погромист
412 / 248 / 30
Регистрация: 27.08.2012
Сообщений: 550
Завершенные тесты: 1
04.01.2013, 17:13 6
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
 #include <iostream>
 
using namespace std;
 
void func (char a)
{
     a = 'l';
     cout << "\nin func a = " << a;
} 
 
int main(){
    char a = 'H';
    cout << "\nin main a = " << a;
    func (a);
    cout << "\nafter func a = " << a;
    system ("PAUSE");
    return 0;
 }
Допустим, нам нужно, чтобы функция поменяла значение а. Тогда делаем через указатели
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
 #include <iostream>
using namespace std;
 
void func (char* a)
{
     *a = 'l';
     cout << "\nin func a = " << *a;
} 
 
int main(){
    char a = 'H';
    cout << "\nin main a = " << a;
    func (&a);
    cout << "\nafter func a = " << a;
    system ("PAUSE");
    return 0;
 }
0
taras atavin
4205 / 1768 / 211
Регистрация: 24.11.2009
Сообщений: 27,565
04.01.2013, 17:22 7
Указатель есть данное, хранящее адрес подпрограммы, или другого данного. Указатель на не указатель называется простым, указатель на указатель кратным, указатель на указатель на не указатель двойным, указатель на указатель на указатель на не указатель тройным и так далее. Сколько указателей надо пройти, чтоб добраться до неуказателя, в том числе, до составного данного, содержащего в том числе, но не только указатели, такова кратность.

Добавлено через 2 минуты
Цитата Сообщение от Nick Alte Посмотреть сообщение
Для обращения непосредственно к объекту используется разыменование (*),
разыменование есть операция, "говорящая" компилятору, что на низком уровне указатель должен быть использован для косвенной адресации, то есть операция разыменования читает из своего операнда (указателя) его значение, которое есть адрес и осуществляет доступ по этому адресу.

Добавлено через 4 минуты
Цитата Сообщение от Nick Alte Посмотреть сообщение
Ссылка "маскируется" под какой-то конкретный объект.
Ссылка - это синоним другого данного. Можно считать, что ссылка - это нечто, ведущее себя как указатель, неявно (то есть без прямого на то указания в исходном тексте) разыменуемый при каждом обращении к нему. Но стандарт не гарантирует, что ссылка будет реализована именно так. Единственный случай, когда в этом можно быть уверенным - это ссылка-параметр не инлайнового оператора (если такие бывают), или неинлайновой подпрограммы, так как в этом случае нет технической возможности реализовать ссылку как либо ещё, кроме синтаксической надстройки над указателем.
0
Kastaneda
Jesus loves me
Эксперт С++
4949 / 3026 / 346
Регистрация: 12.12.2009
Сообщений: 7,628
Записей в блоге: 2
Завершенные тесты: 1
04.01.2013, 17:25 8
Цитата Сообщение от taras atavin Посмотреть сообщение
для косвенной адресации
может и для прямой, тут как компилятору будет удобно.
0
~B~
6 / 6 / 1
Регистрация: 12.06.2011
Сообщений: 80
04.01.2013, 17:26 9
Цитата Сообщение от gomodril Посмотреть сообщение
int si_1 = (int&) si;
так разве можно?
0
taras atavin
4205 / 1768 / 211
Регистрация: 24.11.2009
Сообщений: 27,565
04.01.2013, 17:26 10
Как звёздочка в декларации, или операторе приведения типа говорит об указателе, или повышает его кратность, а в остальных местах становится операцией разыменования, так и амперсанд в декларации означает ссылку, а в любом другом месте операцию взятия адреса. Эта операция берёт адресе своего операнда, потом его можно присвоить указателю (ведь адрес - это значение указательного типа). Семантически эта операция обратна операции разыменования.
0
~B~
6 / 6 / 1
Регистрация: 12.06.2011
Сообщений: 80
04.01.2013, 17:27 11
http://www.cplusplus.com/doc/tutorial/pointers/
вот тут отлично объясняется, если с инглишом проблем нет
0
taras atavin
4205 / 1768 / 211
Регистрация: 24.11.2009
Сообщений: 27,565
04.01.2013, 17:27 12
Цитата Сообщение от Kastaneda Посмотреть сообщение
может и для прямой, тут как компилятору будет удобно.
Прямая - это адрес в коде, а в разыменовании он берётся из данного.
0
Kastaneda
Jesus loves me
Эксперт С++
4949 / 3026 / 346
Регистрация: 12.12.2009
Сообщений: 7,628
Записей в блоге: 2
Завершенные тесты: 1
04.01.2013, 17:29 13
Цитата Сообщение от taras atavin Посмотреть сообщение
Можно считать, что ссылка - это нечто, ведущее себя как указатель, неявно (то есть без прямого на то указания в исходном тексте) разыменуемый при каждом обращении к нему. Но стандарт не гарантирует,...
Да, если ссылка не используется как передаваемый параметр, то компилятор на этапе построения таблицы имен может просто связать имя ссылки с адресом переменной, т.е. получится просто синоним для переменной.

Добавлено через 1 минуту
Цитата Сообщение от taras atavin Посмотреть сообщение
Прямая - это адрес в коде, а в разыменовании он берётся из данного.
Цитата Сообщение от taras atavin Посмотреть сообщение
что на низком уровне указатель должен быть использован для косвенной адресации
Если говорить о низком уровне, то прямая - это использование адреса (того, что в указателе), а косвенная - это когда адрес предварительно кладется в регистр.
0
~B~
6 / 6 / 1
Регистрация: 12.06.2011
Сообщений: 80
04.01.2013, 17:31 14
а не могли бы вы привести пример с использованием инкрементирования указателя для определенных задач, связанных с массивом?
0
taras atavin
4205 / 1768 / 211
Регистрация: 24.11.2009
Сообщений: 27,565
04.01.2013, 17:35 15
Но ведь адрес то не в коде операции, он вообще вынесен за пределы кода и указатель текущей операции на него попасть ни как не может. Сначала надо загрузить данное, а потом уже использовать, как адрес. Но процессор не способен загрузить какое либо данное куда то кроме регистра.

Добавлено через 1 минуту
Цитата Сообщение от ~B~ Посмотреть сообщение
а не могли бы вы привести пример с использованием инкрементирования указателя для определенных задач, связанных с массивом?
Вывод массива в поток:
C++
1
2
3
4
5
6
int a[10]={431, 312, 42, 13, 431, 5531, 53, 5, 5, 131};
int *p;
for (p=a; p<=a+9; ++p)
{
 std::cout<<*p<<", ";
}
.
1
gomodril
6 / 6 / 0
Регистрация: 10.10.2012
Сообщений: 140
04.01.2013, 17:35  [ТС] 16
Цитата Сообщение от taras atavin Посмотреть сообщение
Как звёздочка в декларации, или операторе приведения типа говорит об указателе, или повышает его кратность, а в остальных местах становится операцией разыменования, так и амперсанд в декларации означает ссылку, а в любом другом месте операцию взятия адреса. Эта операция берёт адресе своего операнда, потом его можно присвоить указателю (ведь адрес - это значение указательного типа). Семантически эта операция обратна операции разыменования.
Т.е. это:

char si = 'H';
int si_1 = (int&) si;

То же самое что и:

char si = 'H';
int * si_1 = &si;

Я правильно понимаю?
0
Kastaneda
04.01.2013, 17:36
  #17

Не по теме:

Цитата Сообщение от taras atavin Посмотреть сообщение
Но процессор не способен загрузить какое либо данное куда то кроме регистра.
Способен - может так же писать/читать в/из памяти. Например
Assembler
1
2
mov [0x12345678], еах; пишем значение из регистра ЕАХ в память по адресу DS:0x12345678
mov [0x12345678], 0х123; пишем значение 0х123 в память по адресу DS:0x12345678
точно так же можно производить арифметические операции с памятью/регистром.

0
taras atavin
4205 / 1768 / 211
Регистрация: 24.11.2009
Сообщений: 27,565
04.01.2013, 17:41 18
Цитата Сообщение от gomodril Посмотреть сообщение
int si_1 = (int&) si;
В операторе приведения типа разрешено использовать звёздочку при приведении к указательному типу, а оперсанд там не должен поддерживаться по логике своих значений: нельзя привести к ссылке и нельзя брать адрес в операторе приведения, а только отдельной операцией.

Добавлено через 1 минуту
Цитата Сообщение от Kastaneda Посмотреть сообщение
Способен - может так же писать/читать в/из памяти. Например
Читать куда? А писать в память - это, видимо, из регистра. Ну может какие то процессоры ещё могут из кода. Но надо то в процессор, а не в память, а кроме регистров в нём для этого места нет.

Добавлено через 53 секунды
Цитата Сообщение от Kastaneda Посмотреть сообщение
mov [0x12345678], 0x123; пишем значение 0x123 в память по адресу DS:0x12345678
Это сохранение в память, а я пишу о загрузке данных в процессор.

Добавлено через 51 секунду
Цитата Сообщение от gomodril Посмотреть сообщение
char si = 'H';
int * si_1 = &si;
нет.
C++
1
2
char si='H';
int *si_1=(int*)&si;
Добавлено через 25 секунд
Цитата Сообщение от gomodril Посмотреть сообщение
char si = 'H';
int si_1 = (int&) si;
А так нельзя.
0
coloc
погромист
412 / 248 / 30
Регистрация: 27.08.2012
Сообщений: 550
Завершенные тесты: 1
04.01.2013, 17:43 19
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
#include <iostream>
 
using namespace std;
 
void displayArray (int array[], int size)
{
     cout << "Elements:\n";
     
     int* pArray = array;
     for (int i = 0; i < size; i++, pArray++)
     {
         cout << i << ": " << *pArray << "\n";
     }
     cout << "\n";
}
 
 
int main()
{
    int array [] = {5,546,4,6,1};
    displayArray (array,5);    
    system ("PAUSE");
    return 0;
}
Простенький пример операции вывода на экран массива с помощью указателя
1
Kastaneda
04.01.2013, 17:46     Расскажите популярно про ссылки и указатели
  #20

Не по теме:

Цитата Сообщение от taras atavin Посмотреть сообщение
Это сохранение в память, а я пишу о загрузке данных в процессор.
Не совсем понимаю о чем ты. Есть указатель, в нем адрес. Задача - записать что-нибудь по этому адресу. Выглядеть это все будет где-то так
Assembler
1
2
mov edx, [0x123]; допустим 0x123 это адрес указателя
mov [edx], 0x123; пишем в память, на которую указывает указатель, значение 0х123
это как раз пример косвенной адресации. Но компилятор может знать, на какую переменную указывает данный указатель и сделать прямую адресацию (это в случае оптимизации). Т.е. выглядеть это будет так
Assembler
1
mov [0x123], 0x123; что либо грузить в процессор не обязательно

0
04.01.2013, 17:46
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
04.01.2013, 17:46
Привет! Вот еще темы с ответами:

Расскажите на пальцах про классы
Доброе время суток! (сразу оговорюсь, можете кинуть ссылкой куда мне пойти...

Расскажите пожалуйста про флаги
Доброго времени суток. Помогите пожалуйста разобраться с фалагми. Вот код:...

Расскажите про IDE Intel Parallel Studio XE 2015
Реклама на сайте Intel Parallel Studio XE 2015 написано хорошо, а тех кто...


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

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

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