...
Osoitinmuuttujat
...
ja
...
muuttujan
...
osoite
...
...
...
Muuttuja
...
voi
...
sisältää
...
arvon
...
tai
...
osoitteen.
...
Kun
...
tietoa
...
täytyy
...
välittää
...
funktioille
...
suuri
...
määrä
...
yhdellä
...
kertaa
...
tai,
...
kun
...
tiedonkulun
...
on
...
oltava
...
kaksisuuntaista,
...
täytyy
...
tieto
...
välittää
...
osoitteen
...
avulla.
...
Esimerkiksi
...
haluttaessa
...
välittää
...
taulukko
...
toiselle
...
funktiolle,
...
annetaan
...
tyypillisesti
...
kutsuttavalle
...
funktiolle
...
tiedoksi
...
paikka,
...
missä
...
kohdassa
...
muistia
...
taulukko
...
sijaitsee,
...
eikä
...
kaikkia
...
taulukon
...
alkioita
...
erikseen.
...
Kaikki
...
merkkijonot
...
välitetään
...
funktioilta
...
toiselle
...
osoitteiden
...
avulla.
...
Osoitinmuuttuja
...
esitellään seuraavasti:
Code Block |
---|
int seuraavasti: int\* OsoitinKokonaisLukuun; float\* OsoitinReaalilukuun; char\* OsoitinMerkkiinTaiMerkkijonoon; double\* OsoitinPitkaanReaalilukuun; void \*Tavuosoitin; |
Tähti
...
tyypin
...
ja
...
muuttujan
...
nimen
...
välissä
...
kertoo,
...
että
...
kyseessä
...
on
...
osoitin.
...
p
...
kirjainta
...
käytetään
...
usein
...
muuttujan
...
edessä
...
ilmoittamaan
...
tätä
...
(p
...
=
...
pointer
...
=
...
osoitin).
...
Edellä
...
esitellyillä
...
osoitinmuuttujilla
...
voidaan
...
nyt
...
osoittaa
...
vastaavan
...
tyypin
...
muuttujiin.
...
Osoittimen
...
esittelyn
...
jälkeen,
...
osoitin
...
on
...
ns.
...
"villi"
...
osoitin
...
(wild
...
pointer),
...
koska
...
se
...
ei
...
osoita
...
vielä
...
mihinkään.
...
Tällaisen
...
osoittimen
...
käyttö
...
on
...
erittäin
...
vaarallista.
...
Monesti
...
osoitin
...
laitetaan
...
osoittamaan
...
"ei
...
minnekään"
...
seuraavalla tavalla:
Code Block |
---|
int tavalla: int\* pLuku=NULL; |
Edellä
...
esitetty
...
esittely
...
takaa
...
sen
...
ettei
...
ko.
...
osoitinta
...
voi
...
käyttää
...
ennen
...
kuin
...
se
...
on
...
alustettu
...
osoittamaan
...
jotain
...
muuttujaa
...
esim. seuraavasti:
Code Block |
---|
seuraavasti: int Luku;//esitellään muuttuja nimeltään Luku pLuku=&Luku;//Sijoitetaan muuttujan Luku osoite osoiteeseen pLuku if(pLuku==NULL) printf("VIRHE, LUVATON OSOITTIMEN KÄYtTÖKÄYTTÖ"); |
&-merkillä
...
haetaan
...
esitellyn
...
muuttujan
...
osoite.
...
Osoitetta
...
vastaava
...
muuttuja
...
Monessa
...
tapauksessa
...
tiedetään,
...
missä
...
tieto
...
on
...
eli
...
tiedetään
...
tiedon
...
osoite.
...
Esim.
...
kaikki
...
tietokoneeseen
...
liitetyt
...
laitteet
...
ovat
...
tietyissä
...
osoitteissa.
...
Osoitetta
...
vastaava
...
muuttuja
...
saadaan
...
*
...
merkillä. esim.
Code Block |
---|
esim. char Merkki; char\* pSarjaportti=0x0238;//sarjaportti on liitetty osoitteeseen 0x238 Merkki= \*pSarjaportti; |
Esim.
Code Block |
---|
Esim. int Eka=5; int \*pLuku=NULL; int OmaLuku=0; pLuku = &Eka;//pLuku osoittamaan OmaLuku muuttujaa OmaLuku = \*pLuku;//pLuku osoitteen osoittaman muistipaikan sisältö OmaLuku muuttujalle |
Edellä
...
olevassa
...
esimerkissä
...
muuttujaan
...
Eka
...
sijoitetaan
...
arvo
...
viisi,
...
pLuku
...
laitetaan
...
osoittamaan
...
muuttujaa
...
Eka.
...
Seuraavaksi
...
haetaan
...
pLukua
...
vastaava
...
muuttuja
...
*:llä
...
ja
...
sijoitetaan
...
se
...
muuttujaan
...
OmaLuku
...
Osoitin
...
osoittaa
...
muuttujan
...
paikkaa
...
muistissa.
...
Osoitinmuuttuja
...
on
...
erityinen
...
muuttuja,
...
joka
...
sisältää
...
tiettyyn
...
tyyppiin
...
määritellyn
...
osoittimen.
...
Osoittimilla
...
on
...
C-kielessä
...
kolme
...
tärkeää
...
tehtävää:
...
niillä
...
voidaan
...
osoittaa
...
nopeasti
...
vektorin
...
tai
...
taulukon
...
elementteihin,
...
ne
...
mahdollistavat
...
kaksisuuntaisen
...
tiedon
...
siirron
...
funktioiden
...
välillä
...
ja
...
kolmantena
...
ne
...
tukevat
...
linkattuja
...
listoja
...
ja
...
dynaamisia
...
tietorakenteita.
...
Osoittimien
...
oikea
...
ymmärtäminen
...
on
...
erittäin
...
tärkeää
...
tehokkaan
...
C-ohjelmoinnin
...
kannalta.
...
Osoittimet
...
ovat
...
yksi
...
C:n
...
vahvimmista,
...
mutta
...
myös
...
vaarallisimmista
...
piirteistä.
...
Alustamaton
...
osoitin
...
saattaa
...
aiheuttaa
...
koko
...
ohjelman
...
romahtamisen
...
ja
...
mikä
...
pahinta
...
osoittimien
...
aiheuttamia
...
virheitä
...
on
...
erittäin
...
vaikea
...
löytää,
...
koska
...
ohjelman
...
antamat
...
virheilmoitukset
...
ko.
...
tapauksessa
...
osoittavat
...
tyypillisesti
...
väärään
...
paikkaan.
...
Lisäksi
...
ohjelma
...
saattaa
...
toimia
...
pitkiäkin
...
aikoja
...
näennäisen virheettömästi.
Code Block |
---|
virheettömästi. int Luku; int\* pLuku; int*\* ppLuku; Osoitteen osoite Osoite |
Osoitteen osoite Osoite Muuttuja
&&Luku &Luku Luku
&pLuku pLuku *pLuku
ppLuku *ppLuku **ppLuku
Yllä oleva taulukko esittää, kuinka voidaan siirtyä muuttujasta sen osoitteeseen ja päin vas-
toin.
Tiedonvälitys osoitteiden avulla
Esimerkki tiedonvälityksestä osoittimen avulla.
Code Block |
---|
//esittelyt Muuttuja &&Luku &Luku Luku &pLuku pLuku *pLuku ppLuku \*ppLuku \**ppLuku Yllä oleva taulukko esittää, kuinka voidaan siirtyä muuttujasta sen osoitteeseen ja päin vas\- toin. h2. Tiedonvälitys osoitteiden avulla Esimerkki tiedonvälityksestä osoittimen avulla. //esittelyt void JokuFunktio(int*); void main(); void main() \{ { int Luku=5; JokuFunktio(&Luku); printf("Luvun arvo on %d",Luku); getch(); } getch(); } void JokuFunktio(int\* pMuuttuja) \{ \{ *pMuuttuja = \*pMuuttuja * 2; } Tähdellä on kolme merkitystä: \* hakee osoitetta vastaavan muuttujan \* esittelee osoitinmuuttujan \* toimii myös kertomerkkinä h2. Osoittimen määrittäminen vektorille Osoitin vektorille on vektorin nimi ilman indeksiä. Esim. } |
Tähdellä on kolme merkitystä:
* hakee osoitetta vastaavan muuttujan
* esittelee osoitinmuuttujan
* toimii myös kertomerkkinä
Osoittimen määrittäminen vektorille
Osoitin vektorille on vektorin nimi ilman indeksiä.
Esim.
Code Block |
---|
int p*; //kokonaislukuosoitin int testi[20]; // int p*; /*kokonaislukuosoitin*/ int testi\[20\]; /*20:n kokonailuvun vektori*/ p = testi; /* //kokonaislukuvektorin ensimmäisen elementin osoitin sijoitetaan osoittimen p arvoksi*/ |
Edellenen
...
käsky
...
voidaan
...
toteuttaa
...
myös
...
& merkillä
Code Block |
---|
merkillä testi = &testi\[0\]; h2. Osoitinaritmetiikkaa Osoittimiin voidaan kohdistaa ainoastaan kaksi laskutoimitusta, yhteen\- ja vähennyslasku. Laskenta on turvallisinta \+\+ ja \-\- operaattoreita käyttäen, jotta osoitin osoittaa aina muuttujan alkuun. int |
Osoitinaritmetiikkaa
Osoittimiin voidaan kohdistaa ainoastaan kaksi laskutoimitusta, yhteen- ja vähennyslasku.
Laskenta on turvallisinta ++ ja -- operaattoreita käyttäen, jotta osoitin osoittaa aina muuttujan
alkuun.
Code Block |
---|
int *p; float *f; int lukuja[10]; float flukuja[10]; \*p; float \*f; int lukuja\[10\]; float flukuja\[10\]; p=lukuja;//laitetaan kokonaislukuosoitin osoittamaan vektorin alkuun f=flukuja; p++;//siirrytään seuraavaan alkioon f++; |
p:n
...
arvo
...
nousee
...
laskutoimituksessa
...
kahdella
...
ja
...
f:n
...
arvo
...
kahdeksalla(riippu
...
ympäristöstä,
...
tarkasta
...
sizeof
...
funktiolla
...
lukualueiden
...
koko),
...
koska
...
kokonaisluku
...
on
...
kaksi
...
tavua
...
ja
...
liukuluku
...
kahdeksan
...
tavua
...
pitkä.
...
Osoittimien
...
vertailu
...
Osoittimia
...
voidaan
...
vertailla
...
keskenään esim.
Code Block |
---|
esim. if (p<q) printf("p osoittaa pienempään muistiosoitteeseen kuin q"); |
Osoitinvertailuja
...
joudutaan
...
käyttämään
...
erityisesti
...
tapauksissa,
...
joissa
...
tarvitaan
...
pinoa.
...
Tyypillisiä
...
sovellutuksia
...
ovat
...
kääntäjät,
...
tulkit
...
ja
...
taulukkolaskentaohjelmat.
...
(eli
...
ei
...
tavallista)
...
Osoittimet
...
ja
...
vektorit
...
Osoittimien
...
ja
...
vektoreiden
...
välillä
...
on
...
läheinen
...
yhteys esim.
Code Block |
---|
esim. char strMerkkiJono\[80\], \*psrtMerkkiJono; psrtMerkkiJono = strMerkkiJono; |
p1
...
asetettiin
...
osoittamaan
...
ensimmäistä
...
vektorin
...
elementtiä.
...
Kun
...
halutaan
...
osoittaa
...
neljättä
...
el
...
-
...
ementtiä,
...
voidaan
...
kirjoittaa:
str[3]
tai
*(p1+3)
...
Vektoreita
...
voidaan
...
osoittaa
...
osoitinaritmetiikalla
...
tai
...
vektorin
...
indeksien
...
avulla.
...
Osoitin
...
arit
...
-
...
metiikka
...
on
...
ohjelman
...
kannalta
...
nopeampi
...
tapa.
...
...
void osoitin
void-tyyppinen
...
osoitin
...
on
...
ns.
...
geneerinen
...
osoitin.
...
Geneerinen
...
osoitin
...
voi
...
osoittaa
...
minkä
...
tahansa
...
tyypin
...
muuttujaan.
...
Esimerkiksi
...
seuraavat
...
ohjelmalauseet
...
ovat sallittuja.
Code Block |
---|
sallittuja. char MerkkiJono\[80\]; void\* OsoitinMihintahansa=NULL; OsoitinMihintahansa=Merkkijono; |
Geneerisen
...
osoittimen
...
inkrementointi
...
ja
...
degrementoinit
...
muuttavat
...
osoittimen
...
asemaa
...
yhden
...
tavun
...
verran.
...
Geneerisiä
...
osoittimia
...
käytetään
...
tyypillisesti
...
laiteläheisessä
...
ohjelmoinnissa.
...
Osoitin paluuarvona
Paikallisen muuttujan osoitetta ei saa palauttaa, koska paikallinen muuttuja häviää funktiosta poistuttaessa.
Code Block |
---|
int ---- h2. Osoitin paluuarvona Paikallisen muuttujan osoitetta ei saa palauttaa, koska paikallinen muuttuja häviää funktiosta poistuttaessa. int\* funktio() { int a; // tilapäinen muuttuja, vapautetaan funktiosta poistuttaessa int \*tulos = &a; // sijoitetaan tulos-osoittimeen a:n muistipaikan osoite return tulos; // VIRHE\!\!\! a on paikallinen muuttuja } |
Oikea
...
ratkaisu
Code Block |
---|
int\* funktio(int\* a) //a on nyt kutsujan jonkin muuttujan osoite { int \*tulos = a; // sijoitetaan tulos-osoittimeen a:n osoite return tulos; // OIKEIN } } |
Toinen
...
mahdollinen
...
ratkaisu
Code Block |
---|
int\* funktio() { static int a; // staattista muuttujaa ei vapauteta funktiosta poistuttaessa int \*tulos = &a; // sijoitetaan tulos-osoittimeen a:n muistipaikkan osoite return tulos; // VIRHE\!\!\! } |