Co siedzi w pamięci AnsiStringa i tablic dynamicznych?

0

Tworzę sobie tablice dynamiczną:

type
  TMyTab = array of integer;
var
   MyTab = TMyTab;
begin
   SetLength( MyTab, 100 );
   ShowLength( MyTab );
end;

Wywołuję procedure ShowLength która jako parametr przyjumuje tablice MyTab:

procedure ShowLength( _tab : TMyTab );
begin
   Showmessage( format( '%d', [ Length( _tab ) ] );
end;

Pytanie:
co ja tak naprawde przekazałem w parametrze funkcji?
nie jest to wskaźnik chyba? gdzieś w tym czymś musi zawierać się informacjia o długośc i adresach komórek. tak samo,, jak to jest z AnsiStringami? jak to wyglada w pamięci?

0
TLesiu napisał(a)

co ja tak naprawde przekazałem w parametrze funkcji?

A może Tobie chodzi o to, w jaki sposób przekazywana jest zawartość zmiennej/stałej do procedury/funkcji?

Jeśli tak, to przeczytaj: Kompendium - Typy parametrów przekazywanych do procedur i funkcji - jest tam opisane czym różni się przekazanie przez stałą, przez referencję (działa jak wskaźnik do zewnętrznej zmiennej), przez wartość i za pomocą dyrektywy out (połączenie const i var);

W Twoim przykładzie wykorzystałeś przekazanie przez wartość, więc tablica zostanie skopiowana (@Azarien dokładniej wytłumaczył - dopóki parametr nie jest modyfikowany - nie zostaje skopiowany); Argument działa wtedy na zasadzie lokalnej zmiennej - możesz ją modyfikować, ale zmiany nie zostaną przekazane "wyżej"; Najprostszy przykład:

  procedure ChangeString(AString: ANSIString);
  begin
    AString := 'delphi';
    WriteLn(AString);
  end;

var
  ansiValue: ANSIString = 'pascal';
begin
  WriteLn(ansiValue);
  ChangeString(ansiValue);
  WriteLn(ansiValue);
  ReadLn;
end.

W konsoli zostanie wyświetlone:

pascal
delphi
pascal

Jeśli dopiszesz do argumentu dyrektywę var:

procedure ChangeString(var AString: ANSIString);

to po zmodyfikowaniu argumentu AString zostanie także zaktualizowana zmienna ansiValue, w rezultacie w konsoli pojawi się tekst:

pascal
delphi
delphi

W Twoim przypadku jeśli potrzebujesz argument wykorzystać jedynie do odczytu - możesz przekazać argument przez stałą - daje to możliwość lepszej optymalizacji kodu;

Po więcej informacji odsyłam przede wszystkim do kompendium, kursów programowania w delphi, a ostatecznie do Google; Wątek zaś przenoszę do działu dla początkujących, bo dotyczy ścisłych podstaw kodzenia.

2

co ja tak naprawde przekazałem w parametrze funkcji?
nie jest to wskaźnik chyba? gdzieś w tym czymś musi zawierać się informacjia o długośc i adresach komórek.

Przekazywany jest wskaźnik, wskazujący na tablicę. Tuż przed tablicą (czyli jakby na ujemnych indeksach) przechowywane są różne dane, jak rozmiar i aktualna liczba referencji.

Ansistringi działają bardzo podobnie, z tym że dochodzi mechanizm "copy-on-write", czyli przekazywania samego wskaźnika jeśli string jest tylko odczytywany, ale wykonywania kopii stringa gdy jest dokonywana modyfikacja (tak że zmianie ulega tylko kopia, a nie oryginalny string).

Dokładny format w pamięci tablicy dynamicznej i ansistringa może się zmieniać z wersji na wersję.

Przytoczę przykład @furious programming:

  procedure ChangeString(AString: ANSIString);
  begin
    // przekazano tylko wskaźnik na stringa, więc operacja jest szybka
    // i niezależna od długości stringa (nie jest kopiowany string)

    // ale już w następnej linijce, ponieważ parametr nie ma `out` ani `var`,
    // oryginalny string nie może ulec zmianie. powstaje więc nowy string,
    // wskaźnik na którego jest przypisywany do zmiennej AString:
    AString := 'delphi';
    WriteLn(AString);
  end;

copy-on-write pozwala na pozorne przekazanie parametru przez wartość, przy jednoczesnym uniknięciu kopiowania danych kiedy jest to zbędne.

1 użytkowników online, w tym zalogowanych: 0, gości: 1