Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Паскаль, Turbo Pascal, PascalABC.NET
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 16.04.2011, 18:00   #1
sunny_alice
Пользователь
 
Регистрация: 16.04.2011
Сообщений: 46
По умолчанию Не получается разобраться в программе с указателями

Прочитала множество теории, но не могу понять, как работает программа в некоторых местах, точнее, почему именно так.
Написала комментарии там, где что-то не ясно.
Заранее спасибо всем за помощь.

Текст программы:
Код:
program lab3_1;
  uses crt;
  type point=record
                   x,y:real;
             end;
       ppoint=^point;
       pint=^integer;
  var pi1,pi2,pi3:pint;
      pr1,pr2,pr3:^real;
      pnt1:ppoint;
      pnts:array[1..3] of ppoint;
      i:integer;
      x,y:real;
begin
  clrscr;
  new(pi1);
  new(pi2);
  new(pr1);
  new(pnt1);
  x:=1.0;
  y:=2.0;
  pr1^:=8.5;
  pr2^:=pr1^;
  pr3:=pr2; {если вместо этого написать pr3^:=pr2^, то суть не меняется. получается, это вообще не важно?}
  writeln(pr3^:5:2);
  new(pr1); {не пойму, зачем снова выделять память под тот же указатель, мы же это уже делали выше}
  pr1^:=pr1^+pr2^;
  writeln(pr1^:5:2,pr2^:5:2); {pr1 при каждом запуске разное выводится, каждый раз больше}
  readln;
  pnt1^.x:=0.5;
  pnt1^.y:=9.5;
  for i:=1 to 3 do
    begin
      new(pnts[i]);
      pnts[i]^:=pnt1^;
      with pnts[i]^ do
        begin
          pnt1^.x:=x-1.0; {если написать  pnt1^.x:=pnt1^.x-1.0; что-то изменится по сути?}
          y:=y+2.0 {программа берет игрек из массива или тот свободный, который присвоен в начале программы?}
        end
    end;
  writeln(pnts[1]^.x:5:2, pnts[3]^.y:5:2);
  readln;
end.
Результат:
"8.50
8.50 8.50

0.50 11.50"
sunny_alice вне форума Ответить с цитированием
Старый 16.04.2011, 18:26   #2
Daramant
Форумчанин
 
Регистрация: 06.01.2009
Сообщений: 340
По умолчанию

Цитата:
pr3:=pr2; {если вместо этого написать pr3^:=pr2^, то суть не меняется. получается, это вообще не важно?}
pr3:=pr2; - здесь, ты указателю pr3 присваиваешь указатель pr2, т.е. после выполнения этой операции указатели pr3 и pr2 будут указывать на одну и туже ячейку памяти (pr2).
pr3^:=pr2^ - здесь, ты ячейке памяти, на которую указывает указатель pr3,
присваиваешь значение ячейки памяти, на которую указывает указатель pr2.

Цитата:
new(pr1); {не пойму, зачем снова выделять память под тот же указатель, мы же это уже делали выше}
Здесь выделяется память под указатель pr1, а та память, на которую указывал указатель pr1 до этого, становится недоступной (на нее больше нет указателей) - это называется утечкой памяти.

Цитата:
writeln(pr1^:5:2,pr2^:5:2); {pr1 при каждом запуске разное выводится, каждый раз больше}
Разные - потому что ты в pr1^ ничего не записала, так находятся случайные данные.
Цитата:
pnt1^.x:=x-1.0; {если написать pnt1^.x:=pnt1^.x-1.0; что-то изменится по сути?}
Edit: это эквивалентно строке: pnt1^.x:=pnts[i]^.x-1.0;
Цитата:
y:=y+2.0 {программа берет игрек из массива или тот свободный, который присвоен в начале программы?}
здесь y - это pnts[i]^.y
Истинный успех – это то, что Вы сделали в сравнении с тем, что могли бы сделать.
Никогда не бойся делать то, что ты не умеешь. Помни, ковчег был построен любителем. Профессионалы построили "Титаник".

Последний раз редактировалось Daramant; 16.04.2011 в 21:55.
Daramant вне форума Ответить с цитированием
Старый 16.04.2011, 18:49   #3
sunny_alice
Пользователь
 
Регистрация: 16.04.2011
Сообщений: 46
По умолчанию

Цитата:
pr3:=pr2; - здесь ты указателю pr3 присваиваешь указатель pr2, т.е. после выполнения этой операции указатели pr3 и pr2 будут указывать на одну и туже ячейку памяти (pr2).
pr3^:=pr2^ - здесь ты ячейке памяти, на которую указывает указатель pr3,
присваиваешь значение ячейки памяти, на которую указывает указатель pr2.
т.е. если дальше изменить pr2, то в первом случае значение pr3 изменится вместе с pr2, а во втором останется таким же(как старое pr2)?

Цитата:
Здесь выделяется память под указатель pr1, а та память на которую указывал указатель pr1 до этого становится недоступной (на нее больше нет указателей)
- это называется утечкой памяти.
а что при этом происходит с данными, на которые указывал предыдущий pr1?

Цитата:
Разные - потому что ты в pr1^ ничего не записала, так находятся случайные данные.
это не я, это программа из методички) нам нужно просто записать полученный результат, но я пытаюсь еще и разобраться, как это все происходит.
то есть совсем случайные, старое 8.5 вообще к этому отношения не имеет?

Цитата:
это тоже самое.
значит если написать x:=x-1.0 - это также тоже самое? если да, то к чему тогда вообще это лишняя нагроможденность?

Цитата:
здесь y - это pnts[i]^.y
ага, а если бы эта строчка была вне параметра with, то использовался бы вот этот y:=2.0; да?
sunny_alice вне форума Ответить с цитированием
Старый 16.04.2011, 19:11   #4
Daramant
Форумчанин
 
Регистрация: 06.01.2009
Сообщений: 340
По умолчанию

Цитата:
т.е. если дальше изменить pr2, то в первом случае значение pr3 изменится вместе с pr2, а во втором останется таким же(как старое pr2)?
Да, только изменить значение не pr2, а pr2^.
Цитата:
а что при этом происходит с данными, на которые указывал предыдущий pr1?
С данными ничего не происходит, они просто остаются в памяти, но ты не можешь с ними манипулировать, т.к. у тебя нет на них указателя.
Цитата:
то есть совсем случайные, старое 8.5 вообще к этому отношения не имеет?
Случайные - в смысле, значение которое туда было записано кем-то ранее.
Например, ты выделила участок памяти, записала туда число 10, освободила участок памяти.
Затем выделила новый участок памяти, если система тебе выделила тот-же участок, что и в прошлый раз, то так уже будет записано число 10.
Здесь, как раз это и происходит. Когда ты запускаешь программу первый раз, там содержится значение 0, программа записывает туда число 8.5.
При следующем запуске программы, в данном случае получается, что выделяется тот же участок памяти где ранее было записано 8.5. После суммирования там уже будет 17.0 и т.д.
Цитата:
значит если написать x:=x-1.0 - это также тоже самое? если да, то к чему тогда вообще это лишняя нагроможденность?
Это надо спросить у автора программы).
Предполагаю, что здесь может быть задан вопрос на понимание того - что на самом деле с чем складывается и какие значения содержит.
Цитата:
ага, а если бы эта строчка была вне параметра with, то использовался бы вот этот y:=2.0; да?
Да.
Истинный успех – это то, что Вы сделали в сравнении с тем, что могли бы сделать.
Никогда не бойся делать то, что ты не умеешь. Помни, ковчег был построен любителем. Профессионалы построили "Титаник".
Daramant вне форума Ответить с цитированием
Старый 16.04.2011, 19:23   #5
sunny_alice
Пользователь
 
Регистрация: 16.04.2011
Сообщений: 46
По умолчанию

Цитата:
С данными ничего не происходит, они просто остаются в памяти, но ты не можешь с ними манипулировать, т.к. у тебя нет на них указателя.
так, поняла, то есть в идеале перед тем как заново выделять память нужно было написать dispose(pr1), тогда освободится память и данные удалятся, да?

Цитата:
При следующем запуске программы, в данном случае получается, что выделяется тот же участок памяти где ранее было записано 8.5. После суммирования там уже будет 17.0 и т.д.
ага, а как сделать, чтобы оставалось 8.5 каждый раз?

Цитата:
Это надо спросить у автора программы).
Предполагаю, что здесь может быть задан вопрос на понимание того - что на самом деле с чем складывается и какие значения содержит.
Ясно, спасибо)
sunny_alice вне форума Ответить с цитированием
Старый 16.04.2011, 19:32   #6
Daramant
Форумчанин
 
Регистрация: 06.01.2009
Сообщений: 340
По умолчанию

Цитата:
так, поняла, то есть в идеале перед тем как заново выделять память нужно было написать dispose(pr1), тогда освободится память и данные удалятся, да?
Лучше - всегда освобождать выделенную память.
Да, память освободится и может быть повторно использована при попытке выделить память в следующий раз.
Слова: "данные удалятся" - не совсем корректны, данные просто останутся в памяти, т.е. в ячейке памяти останется записанное туда значение.
Цитата:
ага, а как сделать, чтобы оставалось 8.5 каждый раз?
Для этого туда нужно записать 0:
Код:
new(pr1);
pr1^ := 0;
Истинный успех – это то, что Вы сделали в сравнении с тем, что могли бы сделать.
Никогда не бойся делать то, что ты не умеешь. Помни, ковчег был построен любителем. Профессионалы построили "Титаник".

Последний раз редактировалось Daramant; 16.04.2011 в 19:54.
Daramant вне форума Ответить с цитированием
Старый 16.04.2011, 20:00   #7
sunny_alice
Пользователь
 
Регистрация: 16.04.2011
Сообщений: 46
По умолчанию

Цитата:
Да, память освободится и может быть повторно использована при попытке выделить память в следующий раз.
Слова: "данные удаляться" не совсем корректны, данные просто останутся в памяти, т.е. в ячейке памяти останется записанное туда значение.
а смысл тогда освобождать память, если данные там остаются все равно?

Цитата:
Для этого туда нужно записать 0:
а можно не 0 а nil да?
sunny_alice вне форума Ответить с цитированием
Старый 16.04.2011, 20:18   #8
Daramant
Форумчанин
 
Регистрация: 06.01.2009
Сообщений: 340
По умолчанию

Цитата:
а смысл тогда освобождать память, если данные там остаются все равно?
Если писать более крупную программу, в которой будет в больших объемах использоваться диманическая память, то может сложиться ситуация, когда тебе необходимо выделить память, а свободной памяти нет.

Цитата:
а можно не 0 а nil да?
Нет, nil можно присвоить указателю, например pr1 := nil; - что значит, что указатель pr1 никуда не указывает.
Здесь же необходимо в ячейку памяти, на которую указывает указатель pr1 записать значение 0, (т.е. pr1^ := 0; )
Истинный успех – это то, что Вы сделали в сравнении с тем, что могли бы сделать.
Никогда не бойся делать то, что ты не умеешь. Помни, ковчег был построен любителем. Профессионалы построили "Титаник".
Daramant вне форума Ответить с цитированием
Старый 16.04.2011, 20:31   #9
sunny_alice
Пользователь
 
Регистрация: 16.04.2011
Сообщений: 46
По умолчанию

Цитата:
Если писать более крупную программу, в которой будет в больших объемах использоваться диманическая память, то может сложиться ситуация, когда тебе необходимо выделить память, а свободной памяти нет.
Поняла, так и думала, в принципе =)

Про ноль тоже поняла, спасибо.

Еще образовался вопрос на основании вышеотвеченного))
Вот допустим у меня вот такой код будет:
Код:
  pr1^:=8.5;
  pr2^:=pr1^;
  pr3:=pr2;
  pr1^:=1;
  writeln(pr1^:5:2,' ',pr2^:5:2,' ',pr3^:5:2);
по идее после изменения указателя pr1 должно измениться и значение pr2^, а pr3^ остается прежним. почему при выводе они оба остаются прежними, а меняется только pr1^?
вывелось: 1.0 8.5 8.5
sunny_alice вне форума Ответить с цитированием
Старый 16.04.2011, 20:48   #10
Daramant
Форумчанин
 
Регистрация: 06.01.2009
Сообщений: 340
По умолчанию

Цитата:
по идее после изменения указателя pr1 должно измениться и значение pr2^, а pr3^ остается прежним. почему при выводе они оба остаются прежними, а меняется только pr1^?
вывелось: 1.0 8.5 8.5
Давай уточним:
Указатель, это переменная которая хранит адрес, другой переменой.
1. когда мы пишем: p1 - мы обращаемся к указателю (значение адреса).
2. когда мы пишем: p1^ - мы обращаемся к ячейке памяти, на которую указывает указатель p1.
Теперь по твоему примеру:
Код:
  pr1^:=8.5; { в ячейку памяти, на которую указывает указатель pr1, записываем значение 8.5 }
  pr2^:=pr1^; { в ячейку памяти, на которую указывает указатель pr2, записываем значение ячейки памяти, на которую указывает указатель pr1 }
  pr3:=pr2; { присваиваем указателю pr3 значение (адрес) указателя pr2, т.е. теперь оба указателя указываю на одну и туже ячейку памяти, и если потом написать pr2^:=10; то и pr3^ тоже будет иметь значение 10 }
  pr1^:=1; { в ячейку памяти, на которую указывает указатель pr1, записываем 1 }
  writeln(pr1^:5:2,' ',pr2^:5:2,' ',pr3^:5:2);
Истинный успех – это то, что Вы сделали в сравнении с тем, что могли бы сделать.
Никогда не бойся делать то, что ты не умеешь. Помни, ковчег был построен любителем. Профессионалы построили "Титаник".
Daramant вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
проболел,много тем пропустил ... не получается разобраться bennya Фриланс 1 15.01.2011 00:09
не получается разобраться в коде ! разъясните пожалуйста! код внутри! Lion_paint Паскаль, Turbo Pascal, PascalABC.NET 2 16.05.2009 09:30
Товарищи, помогите разобраться с указателями scibern Общие вопросы C/C++ 7 11.01.2009 12:28