
			      FUNKTIONER


Begreppet funktion har vi berrt tidigare, och vi har ocks konstaterat att C
r uppbyggt kring bibliotek av funktioner, som inte r en del av sprket som
det r definierat frn brjan. Dock pgr ett standardiseringsarbete ven med
funktioner, och ANSI har ett frslag under arbete. Till Amiga finns det fr-
sts en massa egna funktioner, och varje annat system har sina specifika bib-
liotek, mer eller mindre portabla. Fr Lattice C 4.0 finns det inte mindre n
fem olika klasser av funktioner med olika hemort: AMIGA, ANSI, LATTICE, UNIX,
XENIX. Funktionerna i klassen AMIGA kan naturligtvis bara anvndas i program
fr Amiga, och dr bara under AmigaDOS. Klassen ANSI r funktioner som anslu-
ter till ANSI-standardfrslaget, och kommer att finnas i alla kompilatorer
till slut. LATTICE innebr att dessa funktioner finns i alla kompilatorer fr
olika system som Lattice tillhandahller. Den som bara anvnder funktioner i
klasserna ANSI och LATTICE r sker p att hans program fungerar p VAX och
MS-DOS och annat ocks ( kllkoden allts, den mste frsts kompileras om 
med en kompilator fr rtt system ). Klasserna UNIX och XENIX hr frsts 
till dessa bda operativsystem fr minidatorer. Att de finns med till Amiga-
kompilatorn innebr att en oerhrd massa program frn minidatorvrlden kan
flyttas till Amiga nstan utan ndringar.  



			FUNKTIONSDEFINITION


En funktionsdefinition bestr av tv delar, en inledning och en huvuddel. I 
det enklaste fallet bestr inledningen bara av funktionens namn och en tom 
parentes. Hr kan ocks ing frprocessorinstruktioner, som d lmpligen str
fre funktionsnamnet, och ibland en del deklarationer, som ska komma efter 
namnet. Huvuddelen bestr av ett block, allts en sammansatt sats. Vi tar ett
enkelt exempel:

 	hejsan()

 	{

 		printf("\n%s", "Hej p dej, vrlden");

 		printf("\n");

 	}

Vi lgger genast mrke till en detalj: Det finns inget semikolon efter funk-
tionens namn. Nej, det har inte blivit bortglmt, ven om det r ett av de
vanligaste felen nybrjaren gr, det r sttet att tala om fr kompilatorn
att detta r en definition av funktionen och inte ett anrop till den.
Den hr funktionen behver inte ngot argument, den behver allts inte matas
med ngot ingngsvrde. Dessutom ger den inte ngot vrde i retur. Vi skulle
allts fr att pongtera det kunna deklarera den som void. Det enda sklet 
att lta bli det r vl egentligen att inte alla kompilatorer tillter typen
void, och att det drfr tyvrr har blivit en konvention att lta bli. De 
flesta system kommer att returnera ett vrde ven fr en funktion som vrt 
exempel. Men om inte programmeraren ger funktionen ngot vrde s blir det 
odefinierat och innehller bara skrp. Det gr inget s lnge man bara inte 
rkar frska anvnda det till ngot. Kom ihg bara att du inte fr ngon 
varning frn kompilatorn fr detta. Alla funktioner som inte deklareras med 
typ kommer kompilatorn att behandla som om de vore av typen int. Resultatet 
av att glmma deklarationen av ngon annan typ n void blir katastrofalt. 
Antag att vi har en funktion som returnerar en float. Om vi glmmer nyckel-
ordet float i deklarationen kommer kompilatorn att betrakta funktionens vr-
de som om den vore en int. Eftersom float har ett helt annat format s blir 
resultatet rena gojan. Och inte blir det bttre om man frsker typomvandla 
till float i stllet. D kommer kompilatorn att tolka funktionens floatvrde
som int och sedan omvandla det till float, med nnu vrre resultat som fljd.



			FUNKTIONSARGUMENT


Ofta mste man mata in ett eller flera vrden till en funktion. Dessa vrden
kallas fr argument. Vi brjar med att se p hur man anger att funktionen ska
ha argument:

 	hejsan (antal)

 	   int antal;

Den frsta raden visar oss att funktionen hejsan har ett argument och att det
heter antal. S deklarerar vi att antal r av typen int. Det r faktiskt den
enda typ av argument som egentligen inte behver deklareras, fr alla argu-
ment som r odeklarerade antas vara just int, men det r god programmerings-
sed att gra det nd. Det gr att gra alltihop p en enda rad ocks, men 
det blir inte lika lttlst:

 	hejsan (int antal;)

Observera att deklarationen av argumenten mste st fre de klammer som mar-
kerar funktionens huvuddel. 

Argumentets uppgift r att reservera plats till det verkliga argument som 
funktionsanropet kommer med, och fr att pongtera att de deklarerade argu-
menten bara reserverar plats, s kallas de fr formella argument.  

En funktion kan ha flera formella argument, de skrivs d som en lista med
kommatecken som separation:

 	hejsan (antal, gurka, senap)

 	   int antal;

 	   float gurka, senap;



			   FUNKTIONSANROP


Nr vi nu med stor tankemda har lyckats definiera en funktion som p ett
revolutionerande stt utfr precis det vi ville, s mste vi frsts anvnda
den ocks. Lt oss anta att funktionen innehller ngot anvndningsomrde fr
sin parameter, den kan till exempel skriva ut en hlsning s mnga gnger som
argumentet anger. Anropet r inte svrt:

  	hejsan (12);

Nu har vi infrt ett verkligt argument, och i funktionen kommer variabeln
antal att f samma vrde som detta. Det verkliga argumentet kan frsts ocks
vara en variabel, bara den har ftt ett vrde av rtt typ:

 	hejsan (vattenmelon);

Variabeln vattenmelon r en int och har ett lmpligt vrde. Den behver inte
alls heta detsamma som i funktionen frsts, det r ju i C bara vrdet som 
verfrs och inte variabeln. Lgg mrke till semikolonet, som anger att det 
r frga om ett anrop och inte en definition.

Men om man nu verkligen vill att funktionen ska arbeta med variabeln sjlv
och inte bara dess kopia? Jo, det finns en lsning p det problemet ocks. 
Det r bara att ge funktionen en pekare till variabeln som argument och p
s stt kan funktionen hitta originalvariabeln och pverka den i stllet. Ett
speciellt problem utgr vektorer, det r inte tilltet fr en funktion att 
returnera en vektor, s dr mste man arbeta med pekare. Dremot r det t-
minstone i Lattice C tilltet att en funktion returnerar en struktur eller en
union. Egentligen r det dock bara en pekare till en statisk kopia av struk-
turen som man fr, och det gller att utnyttja den omedelbart fr att gra 
en egen kopia, fr den frsvinner omedelbart annars. Detta sker i funktions-
anropet genom att returvrdet tilldelas en struktur av samma slag. Exempel:

 	struct GURKA            /* strukturen GURKA definieras hr, 
 				   den har tre element av typen int. 
 	{ 			   Detta kallas ocks fr strukturmall */
 	   int x;
 	   int y;
 	   int z;
 	};	


 	struct GURKA squash();	/* Deklaration av en funktion av typen
 				   struct GURKA */
 
 	struct GURKA sallad;    /* Deklaration av en variabel av typen
 				   struct GURKA. Nu reserveras minne 
 				   fr en struktur av denna typ. */
  
 
        struct GURKA squash( a, b, c )   /* Definition av funktionen  
 		 			    squash, som r av typen 	
 	int a, b, c;			    struct GURKA, och allts ska
 					    returnera ett vrde av denna	
 	{				    typ */	
 
 	   struct GURKA tomat;           /* Lokal variabel av typen 
 					    struct GURKA, vars element
 	      tomat.x = a;		    tilldelas vrdena a, b och c */
 	      tomat.y = b;
 	      tomat.z = c;
 
 	   return ( tomat );		 /* Vrdet av tomat returneras, det
 					    sker i form av en pekare, men
 	}				    det framgr inte av kllkoden */
 
 	
 	sallad = squash ( 12, 15, 31 );  /* Funktionsanropet */

Lgg mrke till att vrdet av funktionen squash tilldelas till en struktur-
variabel av samma typ redan i anropssatsen. Det ser ut som om funktionen
skulle returnera hela strukturen, men i sjlva verket kommer allts bara en
pekare till en statisk kopia, och om den inte tilldelas p detta stt s r
kopian borta i nsta gonblick. Man fr allts inte ta emot pekaren och spara
den fr att senare referera till strukturen. Nu anvnde vi ngot nytt igen 
frresten, nmligen return.

  
				RETURN


Nyckelordet return anvndes fr att avsluta utfrandet av en funktion och fr
att bestmma det vrde som funktionen ska fra med sig tillbaka till den som 
kallade p den. Ett ensamt return gr inget annat n att avsluta funktionen
och terfra programstyrningen till den anropande funktionen. Om det dremot
finns ett uttryck, helst inom parentes, efter nyckelordet return, kommer den
avslutade funktionen att tilldelas vrdet av detta uttryck. Vi tar ett par
exempel p return-satser:

 		return;
 
 		return ( 111 );
 
 		return ( c + b * a );
 
 		return ( ++x );
 
 		return ++x;

Det sista exemplet r visserligen korrekt, men det anses som dlig program-
meringssed att utelmna parentesen.

Om det r s att funktionen r deklarerad med en viss typ, s kommer vrdet 
att omvandlas till denna typ.

Det kan finnas ingen, en eller flera return-satser i en funktion. Om det inte
finns ngon s kommer funktionen att avslutas i och med att utfrandet nr 
den avslutande klammern. Detta r fullt korrekt och vanligt om funktionen 
inte behver anta ngot vrde, den br vara av typen void. ven om funktionen
r av annan typ s fungerar programmet, men man fr frsts inte frska an-
vnda returvrdet eftersom det r odefinierat.

En funktion med flera return-satser har normalt ngon form av villkor som
bestmmer vilken av return-satserna som ska utfras.
