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

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
 
Рейтинг: Рейтинг темы: голосов - 50, средняя оценка - 4.64
Svid
5 / 5 / 1
Регистрация: 02.03.2011
Сообщений: 40
#1

Понять указатели:) - C++

10.03.2011, 13:35. Просмотров 6597. Ответов 55
Метки нет (Все метки)

Добрый день!
Совсем недавно начал изучать С++, в основном по методичке, выданной в ВУЗе и по нескольким книгам (Страуструп Б., Стефан Дэвис) и плюс то, что нахожу в интернете. Практически, всё это привязано к ряду лабораторных и контрольных, которые необходимо сделать.
Дошел до указателей....О_о. Проблема вот в чем: те практические примеры, которые показывают использование указателей, не отвечают на вопрос - зачем? То есть, все что сделано в этих примерах с помощью указателей, можно сделать и без них, и нельзя сказать, что это будет сложнее. Из-за этого очень трудно понять смысл указателей и они для меня пока что пустая абстракция.
Есть ли какие-нибудь простые практические примеры, показывающие... почему без указателей не обойтись? Например, очень легко практически объяснить суть цикла или там функции.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
10.03.2011, 13:35     Понять указатели:)
Посмотрите здесь:

Указатели не могу понять - C++
Все вопросы указал в комментариях к коду. Не могу понять почему так #include <iostream> using namespace std; int main() { int...

Не могу понять зачем нужны указатели? - C++
Не как не могу понять зачем нужны указатели. Я знаю что их надо использовать для выделения памяти, но раньше я и без них обходился

Строки (массив char), указатели. Не могу понять логику! Help! - C++
Вообщем проблема в том что выводятся лишние символы в строках.. хотя в них есть признак окончания строк - нулевой байт я новичок в С...

Символьные литералы, указатели и функция. Не могу понять, почему именно так - C++
Доброго времени суток всем! :) Изучаю С++, всегда стараюсь добить до последнего код, чтобы не было непоняток. Но сейчас наткнулся на...

Не могу понять, как "живут" файловые указатели - C++
Не могу понять как живут файловые указатели... Есть у меня файл, и пишу в него 100 интов. Указатель ввода сдвигается на 400, так и надо....

Указатели - C++
int k=5; int *ukaz; ukaz=&k; *ukaz=17; printf("%o\n",ukaz); printf("%o\n",k); system("pause"); Может, что то я делаю не...

Указатели с++ - C++
Здравствуйте. У меня такая проблема. Осталась последняя лабораторная по информатике. Условие такое: "В одномерном массиве, состоящем из...

После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
silent_1991
Эксперт С++
4960 / 3036 / 149
Регистрация: 11.11.2009
Сообщений: 7,027
Завершенные тесты: 1
10.03.2011, 17:22     Понять указатели:) #16
А вы пытались запустить программу, которую я выкладывал?
Svid
5 / 5 / 1
Регистрация: 02.03.2011
Сообщений: 40
10.03.2011, 17:31  [ТС]     Понять указатели:) #17
Да, конечно.
Мне просто не понятны подписи к выводу ( с английским плохо):
Before image swap
In image swap и т.д.

Более того, я в том примере, который из моей методички, убирал указатели ( и ссылки), вызывая функцию с параметрами переменных (a и b), и вот это:
1) В случае использования передачи параметров в виде переменных, аргументам функции присваивается значение передаваемых переменных, тем самым создавая новые переменные, область видимости которых - функция. И меняются значения созданных внутри функции переменных, а значения переменных, передаваемых аргументами никак не изменяется, ибо они лишь однажды передали свои значения для переменных функции.

2) Когда используются указатели в качестве аргументов, аргументы функции принимают не численное значение передаваемых переменных( в данном случае a и b ), а ссылку на ячейки памяти, содержащих значение этих переменных, и внутри функции орудуют уже не новыми переменными, а значениями, хранящимися в адресах, принимаемых в качестве аргументов.
мне понятно...
но вербализовать, то что делают примеры, я не могу. Наверное, дело в том, что до этого с понятием "памяти" я не сталкивался...
silent_1991
Эксперт С++
4960 / 3036 / 149
Регистрация: 11.11.2009
Сообщений: 7,027
Завершенные тесты: 1
10.03.2011, 17:36     Понять указатели:) #18
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
32
33
34
35
36
37
38
39
#include <stdio.h>
 
void real_swap(int *a, int *b)
{
    int temp = *a;
    *a = *b;
    *b = temp;
 
    printf("Реальный обмен местами:\ta = %d\tb = %d\n", *a, *b);
}
 
void image_swap(int a, int b)
{
    int temp = a;
    a = b;
    b = temp;
 
    printf("Мнимый обмен местами:\ta = %d\tb = %d\n", a, b);
}
 
int main(void)
{
    int a, b;
 
    printf("Введите a: ");
    scanf("%d", &a);
    printf("Введите b: ");
    scanf("%d", &b);
 
    printf("До мнимого обмена:  \ta = %d\tb = %d\n", a, b);
    image_swap(a, b);
    printf("После мнимого обмена: \ta = %d\tb = %d\n", a, b);
 
    printf("До реального обмена:  \ta = %d\tb = %d\n", a, b);
    real_swap(&a, &b);
    printf("После реального обмена:\ta = %d\tb = %d\n", a, b);
 
    return 0;
}
Svid
5 / 5 / 1
Регистрация: 02.03.2011
Сообщений: 40
10.03.2011, 18:45  [ТС]     Понять указатели:) #19
Да, очень наглядно.
Но - чувствую себя полным гуманитарием.
Я думаю, что на этом этапе мне пока не понять - зачем нужны указатели, даже Ваш пример на этот вопрос до конца не отвечает - ведь если реализовать это
C++
1
2
3
int temp = a;
    a = b;
    b = temp;
не в теле функции image_swap, а в main то, произойдет реальный обмен... без указателей, ну понятно, что они нужны не для того, чтобы менять значения переменных. Видимо, надо двигаться дальше, а полное понимание придет со временем
Еще раз всем спасибо!
silent_1991
Эксперт С++
4960 / 3036 / 149
Регистрация: 11.11.2009
Сообщений: 7,027
Завершенные тесты: 1
10.03.2011, 18:54     Понять указатели:) #20
Обмен переменных - лишь пример, который показывает, что без указателей в случае, когда в функции надо изменить фактические параметры, не обойтись (про ссылки пока не говорим).

Цитата Сообщение от Svid Посмотреть сообщение
ведь если реализовать это не в теле функции image_swap, а в main то, произойдет реальный обмен
А если у вас в сотне разных мест программы, состоящей из 5000 строк кода, происходит обмен значений? Что, будем писать 200 лишних строчек только потому, что упрямо не желаем согласиться, что даже в такой маленькой функции указатели ого-го как пригодились?
dimon1984
40 / 38 / 0
Регистрация: 22.01.2011
Сообщений: 670
10.03.2011, 19:00     Понять указатели:) #21
так же дополню
C++
1
2
3
4
5
6
7
8
9
void real_swap(int *a, int *b)
{
    int temp = *a;
    *a = *b;
    *b = temp;
 
    printf("Реальный обмен местами:\ta = %d\tb = %d\n", *a, *b);
}
... real_swap(&a, &b);
Здесь указатели как бы указавают, где находятся переменные в памяти, чтобы можно было их изменить.
C++
1
2
3
4
5
6
7
8
void image_swap(int a, int b)
{
    int temp = a;
    a = b;
    b = temp;
 
    printf("Мнимый обмен местами:\ta = %d\tb = %d\n", a, b);
}
а здесь a,b в функции это не те же самые переменные.
Реальные переменные a,b из main соприкасаются с функцией в момент вызова функции
image_swap(a, b);
при этом создаётся копия значений a,b , и в функции уже совсем другие переменные, которые уничтожатся при выходе из функции, а про реальные переменные эта функция и не знает, где они находятся. Поэтому и не может их изменить.
silent_1991
Эксперт С++
4960 / 3036 / 149
Регистрация: 11.11.2009
Сообщений: 7,027
Завершенные тесты: 1
10.03.2011, 19:06     Понять указатели:) #22
dimon1984, перечитайте пятое и вторую половину двенадцатого сообщения в этой теме, и тогда, возможно, перестанете повторять то, что уже не один раз было разжёвано и на что ТС отозвался вполне удовлетворительным ответом "вроде понял".
talis
791 / 543 / 37
Регистрация: 11.05.2010
Сообщений: 1,298
Записей в блоге: 1
10.03.2011, 19:19     Понять указатели:) #23
Сообщение было отмечено автором темы, экспертом или модератором как ответ
Svid, попробую вербализовать некоторые аспекты в менее гуманитарной манере Для начала - думайте об указателях, как об адресах памяти. То есть:

C++
1
2
3
4
5
int var = 18; //допустим, лежит по адресу 0x0022ff74
int * ptr; //указатель
ptr = &var; // ptr = 0x0022ff74
 
cout << ptr << ": " << *ptr << endl;
Вывод:
Код
0x22ff74: 18
Амперсанд (&) - это операция взятия адреса; Вы присваиваете АДРЕС переменной var, а не её значение. Звёздочка перед именем указателя ( *ptr ) - это операция разыменовывания указателя, то есть вы берёте не значение указателя (то есть адрес), а значение, лежащее по этому адресу.

Теперь о практике: представьте себе, что вам нужно написать функцию, которая выводит массив int, но вы заранее не знаете, массив какого размера ей передадут. Это могут быть 2 int'а, а может быть десь-тыщ. В этом случае проще сделать так:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
void int_out( int * array, int size )
{
   for( int i = 0; i < size; i++ )
      cout << array[i] << "; " << endl;
 
   cout << "=============\nTotal " << size << " numbers" << endl;
}
 
int main()
{
   int var = 18; 
   int test[15] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
 
   int_out( &var, 1 ); //передаём адрес var
   cout << endl;
   int_out( test, 15 ); //массивы всегда передаются по указателю; операция взятия адреса не требуется
 
   return 0;
}
Теперь вопрос: вы задумывались, почему в C и C++ нумерация элементов массива идёт с нуля, а не с единицы? Смотрите, вот так выглядит массив в памяти:

00 AF 14 28 A8 76 42 00 00 00 01 00 00 00 02 00 00 04 A1 00 00 A7 70 21 17 86 61 0A

При синтаксисе var[5] берётся адрес начала массива var и к нему прибавляется ( размер_элемента_массива_var * 5 ). То есть нулевой элемент массива int будет равен ( адрес_начала + (4 * 0) = адрес_начала ), первый - ( адрес_начала + (4 * 1) = адрес_начала + 4 ) и так далее. Вы в любом случае работаете с адресами, указатели просто позволяют это делать более просто.

Теперь на счёт ссылки. По сути, ссылка - это константный указатель на неконстантные данные, то есть вы можете изменить данные по ссылке, но не можете изменить адрес, на который она указывает.

Теперь на счёт синтаксиса printf():

C++
1
2
3
4
5
int var = 18;
   
// сначала функции передаётся значение переменной var,
// а затем её адрес
printf( "var = %i\naddress = 0x%x\n", var, &var );
Всё очень просто, если всё понимать.

Другой пример: вам нужно передать функции структуру, которая занимает в памяти 1 килобайт (ну, жирная такая структура). Вы можете либо это запихать целиком и подавиться, а можете вместо 1 килобайта записать 4 байта адреса этой структуры и на этом успокоиться. Что проще будет?

Если что - спрашивайте.

Добавлено через 1 минуту

Не по теме:

О, пока я писал, тема развилась... Если что - простите за повторения, ещё не ознакомился

Svid
5 / 5 / 1
Регистрация: 02.03.2011
Сообщений: 40
10.03.2011, 19:24  [ТС]     Понять указатели:) #24
Да нет, я не
упрямо не желаем согласиться
, я и как раз и хочу понять.
Как объяснить, начинаешь изучать С++ - все понятно и последовательно, переменные,циклы, функции - есть какая-то задача, которая реализовывается с помощью цикла и т.д. А с указателями, такое впечатление, что их понятие вводится намного раньше того, когда их использование становится необходимым.
talis
791 / 543 / 37
Регистрация: 11.05.2010
Сообщений: 1,298
Записей в блоге: 1
10.03.2011, 19:25     Понять указатели:) #25
Возможно, так оно и есть в вашей книжке. Но ведь указатели-то от этого своего значения не теряют Постарайтесь разобраться.
silent_1991
Эксперт С++
4960 / 3036 / 149
Регистрация: 11.11.2009
Сообщений: 7,027
Завершенные тесты: 1
10.03.2011, 19:32     Понять указатели:) #26
Циклы и функции - это понятия, которые позволяют решать задачи (условный переход, как мы помним, совершил революцию в развитии вычислительной техники). Указатели - инструмент, который помогает их решать. Во многих языках нету указателей, поскольку там это не так необходимо. Поэтому указатели можно, по сути, вводить в любом месте материала, и везде они на первых парах будут одинаково непонятны.
Svid
5 / 5 / 1
Регистрация: 02.03.2011
Сообщений: 40
10.03.2011, 19:46  [ТС]     Понять указатели:) #27
Спасибо, talis!
Стало намного понятней, особенно с функцией вывода массива.
Я еще усвою, что Вы написали по поводу того, как выглядит массив в памяти, и думаю, все встанет на свои места.
В методичке, блин, всего этого нет - там указатели появляются как сама собой разумеющаяся вещь
talis
791 / 543 / 37
Регистрация: 11.05.2010
Сообщений: 1,298
Записей в блоге: 1
10.03.2011, 20:08     Понять указатели:) #28
Не за что, Svid. Главное запомните: указатели - это точно такие же переменные, как и char, int, float, double и технически от них не отличаются ровно ничем. Более того, это самые обычные числа, то есть их можно (хотя и не нужно) складывать и вычитать. Иногда даже для перехода на следующий элемент массива используется инкремент указателя - это не всегда хорошая идея, но иногда так делают, и ничего плохого в этом нет, разве что тут выше риск сделать первоклассную утечку памяти. Единственный нюанс - тут значение указателя увеличивается не на 1, а на ( 1 * размер_элемента_массива ), то есть, в случае с int - сразу на 4.

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
int main()
{
   int array[18];
   
   
   // arr = адрес начала массива. Пока arr != адресу последнего элемента + 1 (аккурат конец массива)
   for( int * arr = &array[0]; arr != &array[19]; arr++ )
      *arr = 12;
      
   // оно же:
   //for( int i = 0; i < 18; i++ )
   //   arr[i] = 12;
   
   
   
   
   for( int * arr = &array[0]; arr != &array[18]; arr++ )
      cout <<  *arr << "; ";
   
   // оно же:
   //for( int i = 0; i < 18; i++ )
   //   cout << arr[i] << "; ";
   
   cout << endl;
   system("pause > nul");
   
   return 0;
}
У неё тоже есть свои плюсы.
Feax
9 / 9 / 2
Регистрация: 04.03.2010
Сообщений: 40
11.03.2011, 07:34     Понять указатели:) #29
talis, спасибо за развернутый ответ. Теперь еще понятнее стало Я так понял, что при создании объекта без использования new, объект помещается в кучу, а в стек только указатель на адрес в куче. В таком случае, какие плюсы создания объекта без new? Получается, что структуры, объекты классов лучше создавать в динамической памяти. А тогда почему в книжках ( по Qt например ) создаются часть экземпляров класса без new, а часть с new?
Например, GUI элементы, объект приложения ( QAplication ) в книге создаются без new.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
11.03.2011, 17:21     Понять указатели:)
Еще ссылки по теме:

Указатели С++ - C++
Помогите решить П.5.18. Правил Запрещено размещать задания и решения в виде картинок и других файлов с их текстом.

Указатели. - C++
Да в конце концов, хочу понять и выучить эти указатели. Немного понял, но все же проблемы и хочу узнать ваши советы. практиковался...

указатели - C++
здравствуйте, не получается вывести правельный ответ. код сам идет, только вычисляет не правильно, вот условие: задача на языке СИ) Даны...

Указатели - C++
Добрый вечер, не могу что-то разобраться. В первом CASE определяется M, например М=&quot;kards\\cherv\\&quot; , вот, а во втором CASE мне нужно к...

Указатели - C++
помогите с решением этих задач мне срочно нужно их сдать до аттестации


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

Или воспользуйтесь поиском по форуму:
instagib
122 / 85 / 3
Регистрация: 14.02.2011
Сообщений: 340
11.03.2011, 17:21     Понять указатели:) #30
хоть тему я не открывал, но благодаря Вам всем. я тоже усек что такое указатели и как их использовать . спс удачи всем!
п.с. поставил закладку..если что еще раз прочту
Yandex
Объявления
11.03.2011, 17:21     Понять указатели:)
Ответ Создать тему
Опции темы

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