Llenguatge de programació C (VI). Funcions i Macros
1991/07/01 Alegria Loinaz, Iñaki | Maritxalar, Montse Iturria: Elhuyar aldizkaria
Funcions
Igual que en altres llenguatges d'alt nivell, C ens permet escriure subprogrames. Segons el llenguatge, els subprogrames es denominen de manera diferent, sent el procediment, la funció, la rutina, les subrutines més comunes. Les diferents denominacions es diferencien per característiques diferents de poca importància. Per això, quan diem funció, per exemple en el cas de C, se suposa que el subprograma retornarà implícitament un resultat. El procediment no retorna resultats implícits.
No obstant això, l'objectiu de les funcions de C, igual que el de tots els subprogrames, és facilitar el disseny i l'escriptura en el programa, ja que amb elles és possible separar un problema complex en uns altres més senzills, resolent cadascun amb un programa més senzill. Aquesta tècnica, denominada programació descendent o modular, té en l'actualitat una gran difusió per la millora de l'eficiència (tant en el desenvolupament com en la correcció) dels programadors.
Vegem un exemple, com el cas del factorial. En els dos capítols anteriors hem realitzat diferents programes que calculen el factorial, però sempre en un únic programa. Això no és l'única opció, ja que el càlcul del factorial pot programar-se definitivament en un subprograma o funció i ser utilitzat des de diferents programes principals com s'explica en el programa 1.
![](images/A50029.jpg)
En el programa 2 es pot veure l'ús de la mateixa funció,
m / (m - n)! n
per a calcular l'expressió a través de la fórmula (m / n).
En el segon programa no hem escrit el codi del factorial i caldrà indicar al compilador que la funció es compilarà apart. Per això s'haurà d'indicar el tipus de factorial, especificant el distintiu extern. Amb aquest esquema, el mòdul objecte que es genera en compilar la definició de la funció factorial s'enllaça amb el creat pel programa principal obtenint un únic programa executable.
![](images/A50029-a.jpg)
Com s'ha vist en els exemples, si utilitzem les funcions en els programes C, podem fer al·lusions de tres tipus: definició, crida i desenvolupament.
Definició de la funció
Serveix per a expressar el que fa el subprograma, especificant el tipus de resultat de la funció, el nom, els arguments, la definició dels arguments i el cos.
Si hi ha més d'un argument, es distingeixen pel caràcter. En l'Exemple 1 el nom de la funció és factorial, el tipus de resultat és long, l'argument n, la definició de l'argument int n, i tot el que està al costat del cos fins al programa principal. Cal tenir en compte que el programa principal és una funció anomenada main sense argument.
El format de la definició és el següent:
![](images/A50029-b.jpg)
Si la funció retorna resultats, es farà a través de la sentència return, que normalment és l'última del cos. Si la funció no retorna resultats (en altres llenguatges es diu procediment), s'escriurà com a tipus de resultat el void, ja que si no s'esmenta el tipus de resultat se suposarà la devolució del nombre enter.
La definició dels arguments es realitza com a definició de les dades. L'única diferència és que aquestes dades siguin enviades des d'altres funcions (o des del programa principal). Per això, aquests arguments es denominen formals i en cridar a la funció s'emplenaran amb dades concretes.
En el cos de la funció s'indica el codi del subprograma, indicant tant la definició de les seves dades com les instruccions.
Escriurem la definició que retorna el major número en els dos nombres enters: inventem el nom, els grans, per exemple, els paràmetres són dos i a més els dos nombres enters (els anomenats a i b) i el tipus de resultat és un dels dos números, per la qual cosa serà a més sencer. Per tant, el cap de la funció serà:
int grans (a, b)
int a, b; /*paràmetres de funció */
El cos és molt senzill i una vegada realitzat aquí s'utilitzarà la variable local denominada resultat.
1r resultat
/*Variable local*/ if (a b) resultat = a; else resultat = b; return (resultat)
Pressupostos
Anomenada de la funció
Quan es vol executar una funció es realitza una crida, de manera que amb les dades indicades en la crida (paràmetres) s'executi el codi corresponent a la definició de la funció i es retorna el resultat.
Si la funció retorna resultats, la crida apareixerà normalment a la dreta d'una assignació. No obstant això, també pot aparèixer enmig d'una expressió o com a paràmetre d'una altra funció.
Pensem que hem llegit dos números en les variables z1 i z2 i volem escriure el més gran. Tenim dues opcions:
a) int em; ... em = grans (z1, z2) printf (“%d”, em); ... b) printf (“%d”, grans (z1, z2);
En el programa 2 descrit inicialment es pot observar que la funció factorial es diu tres vegades en un mateix programa, però utilitzant diferents paràmetres.
Quan cal obtenir més d'un resultat en un subprograma, no es pot fer amb sentència return (això permet retornar un únic resultat). Això es farà a través dels paràmetres definits amb referència (veure capítol 10).
Desenvolupament de la funció
Quan en un programa cridem a una funció que està definida en un altre mòdul, la funció ha de ser descrita perquè per falta de definició el compilador no doni error. Això s'ha realitzat en l'Exemple 2 i el que s'ha d'especificar en l'informe és: per a indicar que es defineix externament la paraula clau extern, per a diferenciar el tipus de resultat, el nom de la funció i la funció ( ). En l'exemple que ens ocupa, l'explicació seria la següent.
extern grans int ( );
Quan la funció i la crida estan dins d'un mateix mòdul, no és necessari realitzar el disseny de la funció, si la definició de la funció s'escriu abans de la crida, sinó és necessari l'enviament però sense introduir la paraula clau externa.
Macros
Aquesta eina de programació, tan comuna en els llenguatges d'assemblatge, apareix en uns pocs llenguatges d'alt nivell. Per exemple en C.
Les macros s'utilitzen per a definir i referenciar subprogrames simples, però presenten les següents diferències funcionals:
- les crides no suposen l'execució del subprograma. Per contra, el compilador reemplaça una anomenada al cos de la definició. Per tant, durant la compilació les crides desapareixeran i es compilarà un nou codi.
- els programes executables són més llargs, però més ràpids.
- si no s'utilitzen parèntesi amb els paràmetres, pot haver-hi problemes.
- no són apropiats per a subprogrames complexos.
Definir i referenciar (cridar) les macros. El format de la definició és el següent:
![](images/A50029-c.jpg)
i el cas del major el faríem així:
#defineix grans (x, i) ((x) (i)? (x) : (i)
if
en lloc de l'estructura, ? : s'ha utilitzat l'expressió, ja que en cas contrari no es pot retornar el resultat. Les referències es realitzen igual que les crides de la funció, encara que la manera d'influir és molt diferent.
Amb aquesta referència,
em = grans (zenb1, zenb2);
la substitució del compilador en llenguatge màquina donarà com a resultat:
em = ((zenb1) (zenb2)? (zenb1) : (zenb2)
Així és, perquè el compilador en veure un nom macro el substitueix pel cos de la macro, substituint els arguments formals per paràmetres de referència.
Com es pot observar, el mecanisme és més reduït que el de les funcions, per la qual cosa rares vegades s'utilitza.
Per a finalitzar, col·locarem una macro per a calcular la superfície del cercle:
#defineix PI 3.1416
# defineix superfície (r) PI *(r)*(r)
![](https://elia.eus/static/elhuyar/img/elia_RGB.png)
Gai honi buruzko eduki gehiago
Elhuyarrek garatutako teknologia