REAL, TARGET :: B(10,10)
REAL, POINTER :: A(:,:)
A => B
Ovan har matrisen B deklarerats fullständigt, dvs dimensionen har
angetts explicit. Dessutom
har det angetts att den kan vara mål för en pekare. Matrisen A, som skall användas
som pekare, måste deklareras som en matris, dvs ges rätt antal dimensioner
(rang),
men omfånget
för dessa bestäms först vid tilldelningen (egentligen är
det inte en tilldelning utan en pekar-associering), vilken sker med =>.
Observera att pekar-tilldelningen
inte innebär att data i matrisen B kopieras över till matrisen A
(vilket skulle tagit
relativt stora datorresurser i anspråk), utan det är en adress som
genereras. Att "flytta"
data med pekare är således mycket effektivt. Alternativt kan en pekare
associeras med
kommandot ALLOCATE och av-associeras med DEALLOCATE, i vårt
fall till exempel
ALLOCATE (A(5,5))
DEALLOCATE (A)
Det finns en inbyggd funktion ASSOCIATED för att undersöka om en pekare är associerad
(och även om den är associerad med ett visst mål) och ett kommando NULLIFY för
att avsluta associeringen.
IF ( ASSOCIATED (A) ) WRITE(6,*) ' A associerad'
IF ( ASSOCIATED (A,B) ) WRITE(6,*) ' A associerad med B'
NULLIFY (A)
Notera vidare att en pekare i Fortran 90 har både typ och rang, och att dessa måste
överensstämma med motsvarande hos målet. Detta ökar säkerheten vid
användning av pekare, man kan därför ej av misstag vid användningen av
en viss pekare ändra värden på variabler av andra datatyper. Att man måste
deklarera att en variabel kan vara mål ökar dessutom både säkerheten och
kompileringseffektiviteten.
REAL, TARGET :: A
REAL, POINTER :: P, Q
A = 3.1416
P => A
Q => P
A = 2.718
WRITE(6,*) Q
Här blir värdet av Q lika med 2,718 eftersom både
P och Q pekar på samma
verkliga variabel A, och den har just ändrat värde från 3,1416 till 2,718. Vi
gör nu en enkel variation.
REAL, TARGET :: A, B
REAL, POINTER :: P, Q
A = 3.1416
B = 2.718
P => A
Q => B
Här är nu värdet av både A och P lika med 3,1416 och värdet av både
B och Q är 2,718. Om vi nu ger satsen
Q = P
så får samtliga fyra variabler värdet 3,1416, det får således samma
effekt som
B = A
Om vi i stället gett satsen
Q => P
så hade de tre variablerna A, P och Q fått
värdet 3,1416, medan B behållet
värdet 2,718. I det senare fallet pekar nämligen Q bara på samma variabel som
P, medan i det första fallet Q blir samma som P.
REAL, TARGET :: B(10,10)
REAL, POINTER :: A(:), C(:)
A => B(4,:) ! Vektorn A blir fjärde raden och
C => B(:,4) ! vektorn C blir fjärde kolumnen
! av matrisen B
Det är inte nödvändigt att ta ut hela sektioner, utan man kan ta ut bara en del.
I följande exempel tar vi ut en delmatris FONSTER av en stor matris
MATRIS.
REAL, TARGET :: MATRIS(100,100)
REAL, POINTER :: FONSTER(:,:)
INTEGER :: N1, N2, M1, M2
FONSTER => MATRIS(N1:M1,N2:M2)
Om man senare vill ändra dimensioneringen av delmatrisen FONSTER
så är det bara
att göra en ny pekar-tilldelning. Observera dock att indexen i FONSTER
inte går från
N1 till M1 respektive N2 till M2
utan från 1 till M1-N1+1 respektive 1 till M2-N2+1.
Det finns inte fält av pekare direkt i Fortran 90, men man kan konstruera sådana genom att skapa en ny datatyp. Ett exempel är att lagra en vänstertriangulär matris som rader med varierande längd. Inför först den nya typen RAD
TYPE RAD
REAL, POINTER :: R(:)
END TYPE
och deklarera därefter de två vänstertriangulära matriserna
V och L som
vektorer av rader med varierande längd.
INTEGER :: N
TYPE(RAD) :: V(N), L(N)
Därefter allokeras matrisen V enligt nedan (och motsvarande för L).
DO I = 1, N
ALLOCATE (V(I)%R(1:I)) ! Varierande radlängd
END DO
Satsen
V = L
blir då ekvivalent med att göra
V(I)%R => L(I)%R
för alla komponenterna,
dvs alla värdena på I.
Observera att i denna tillämpning erfordras inget mål (TARGET) för pekarna!
Man kan även använda pekare för att deklarera en vektor på ett sådant sätt att den tilldelas sin storlek (sitt omfång) i en subrutin men kan användas i huvudprogrammet. Detta ger då en dynamisk minnesallokering. Detta har diskuterats utförligt i sektion 4.3.2.
Notera att vid denna användning av pekare behövs inget deklarerat som TARGET, begreppet POINTER är snarast att betrakta som ett alternativ till ALLOCATABLE.
Viktiga tillämpningar av pekare är listor och träd, liksom dynamiska fält.
(12.2) Deklarera två pekare och låt den ena peka på en hel vektor och den andra
på det sjunde elementet i samma vektor.
Lösning.