Förstå och använda pekare i Delphi

Även om pekare inte är lika viktiga i Delphi som i C eller C ++, är de ett så "grundläggande" verktyg att nästan allt som har att göra med programmering måste hantera pekare på något sätt.

Det är av den anledningen du kanske läser om hur en sträng eller objekt egentligen bara är en pekare, eller att en händelsehanterare som OnClick faktiskt är en pekare till en procedur.

Pekare till datatyp

Enkelt uttryckt är en pekare en variabel som har adressen till vad som helst i minnet.

För att konkretisera denna definition, kom ihåg att allt som används av ett program lagras någonstans i datorns minne. Eftersom en pekare har adressen till en annan variabel sägs den peka på den variabeln.

För det mesta pekar pekare i Delphi på en specifik typ:

var
iValue, j: heltal; pIntValue: ^ heltal;
Börja
iValue: = 2001; pIntValue: = @iValue; ... j: = pIntValue ^;
slutet
;

Syntaxen för att deklarera en pekdatatyp använder a caret (^). I koden ovan är iValue en variabel av heltalstyp och pIntValue är en pekare av heltalstyp. Eftersom en pekare inte är något annat än en adress i minnet, måste vi tilldela den platsen (adressen) för värdet som lagras i iValue-heltalvariabeln.

De @ operatör returnerar adressen till en variabel (eller en funktion eller procedur som kommer att ses nedan). Likvärdigt med operatören @ är Addr-funktion. Observera att pIntValues ​​värde inte är 2001.

I denna provkod är pIntValue en typ heltalspekare. Bra programmeringsstil är att använda inskrivna pekare så mycket du kan. Pekdatatypen är en generisk pekartyp; det representerar en pekare till alla data.

Observera att när "^" visas efter en pekarvariabel, avmarkerar den pekaren; det vill säga att det returnerar värdet lagrat på minnesadressen som innehas av pekaren. I detta exempel har variabeln samma värde som iValue. Det kan se ut som att detta inte har något syfte när vi helt enkelt kan tilldela iValue till j, men den här kodkoden ligger bakom de flesta samtal till Win API.

NILing-pekare

Otilldelade pekare är farliga. Eftersom pekare låter oss arbeta direkt med datorns minne, om vi försöker (med misstag) skriva till en skyddad plats i minnet, kan vi få ett fel på åtkomstbrott. Detta är anledningen till att vi alltid bör initialisera en pekare till NIL.

NIL är en speciell konstant som kan tilldelas valfri pekare. När noll tilldelas en pekare hänvisar pekaren inte till något. Delphi presenterar till exempel en tom dynamisk matris eller en lång sträng som en nollpekare.

Teckenpekare

De grundläggande typerna PAnsiChar och PWideChar representerar pekare på AnsiChar- och WideChar-värden. Den generiska PChar representerar en pekare till en Char-variabel.

Dessa teckenpekare används för att manipulera nollavslutade strängar. Tänk på en PChar som en pekare till en noll-avslutad sträng eller till matrisen som representerar en.

Pekare till poster

När vi definierar en post eller annan datatyp är det vanligt att definiera en pekare till den typen. Detta gör det enkelt att manipulera instanser av typen utan att kopiera stora minnesblock.

Möjligheten att ha pekare på poster (och matriser) gör det mycket lättare att skapa komplicerade datastrukturer som länkade listor och träd.

 typ
pNextItem = ^ TLinkedListItem
TLinkedListItem = spela insName: String; iValue: Heltal; NextItem: pNextItem;
slutet
;

Tanken bakom länkade listor är att ge oss möjligheten att lagra adressen till nästa länkade objekt i en lista i ett NextItem-postfält.

Pekare till poster kan också användas när du lagrar anpassad data för varje trädvisningsobjekt, till exempel.

Förfaranden och metodpekare

Ett annat viktigt pekarkoncept i Delphi är procedur- och metodpekare.

Pekare som pekar på adressen till en procedur eller funktion kallas procedurpekare. Metodpekare liknar procedurpekare. Istället för att peka på fristående procedurer måste de dock peka på klassmetoder.

Metodpekaren är en pekare som innehåller information om både namnet och objektet som åberopas.

Pekare och Windows API

Den vanligaste användningen för pekare i Delphi är gränssnitt till C- och C ++ -kod, som inkluderar åtkomst till Windows API.

Windows API-funktioner använder ett antal datatyper som kan vara okända för Delphi-programmeraren. De flesta av parametrarna i anropande API-funktioner är pekare på någon datatyp. Som nämnts ovan använder vi nollavslutade strängar i Delphi när vi kallar Windows API-funktioner.

I många fall, när ett API-samtal returnerar ett värde i en buffert eller pekare till en datastruktur, måste dessa buffertar och datastrukturer allokeras av applikationen innan API-samtalet görs. SHBrowseForFolder Windows API-funktion är ett exempel.

Pekare och minnesallokering

Pekars verkliga kraft kommer från förmågan att avsätta minne medan programmet körs.

Den här kodkoden borde räcka för att bevisa att det inte är så svårt att arbeta med pekare som det kan tyckas i början. Den används för att ändra texten (bildtexten) på kontrollen med det medföljande handtaget.

 procedur GetTextFromHandle (hWND: THandle);
var
pText: PChar; // en pekare till char (se ovan)TextLen: heltal;
Börja

få längden på texten
TextLen: = GetWindowTextLength (hWND);
tilldela minne

GetMem (pText, TextLen); // tar en pekare
få kontrollens text
GetWindowText (hWND, pText, TextLen + 1);
visa texten
ShowMessage (String (pText))
frigöra minnet
FreeMem (pText);
slutet
;