Linguaxe de programación C (VIN). Funcións e Macros

Do mesmo xeito que noutras linguaxes de alto nivel, C permítenos escribir subprogramas. Segundo a linguaxe, os subprogramas reciben diferentes nomes. No entanto, as funcións de C, do mesmo xeito que as de todos os subprogramas, teñen como obxectivo facilitar o deseño e redacción do programa.

Funcións

Do mesmo xeito que noutras linguaxes de alto nivel, C permítenos escribir subprogramas. Segundo a linguaxe, os subprogramas denomínanse de forma diferente, sendo o procedemento, a función, a rutina, as subrutinas máis comúns. As distintas denominacións diferéncianse por características distintas de pouca importancia. Por iso, cando dicimos función, por exemplo no caso de C, suponse que o subprograma devolverá implicitamente un resultado. O procedemento non devolve resultados implícitos.

No entanto, o obxectivo das funcións de C, do mesmo xeito que o de todos os subprogramas, é facilitar o deseño e a escritura no programa, xa que con elas é posible separar un problema complexo noutros máis sinxelos, resolvendo cada un cun programa máis sinxelo. Esta técnica, denominada programación descendente ou modular, ten na actualidade una gran difusión pola mellora da eficiencia (tanto no desenvolvemento como na corrección) dos programadores.

Vexamos un exemplo, como o caso do factorial. Nos dous capítulos anteriores realizamos diferentes programas que calculan o factorial, pero sempre nun único programa. Isto non é a única opción, xa que o cálculo do factorial pode programarse definitivamente nun subprograma ou función e ser utilizado desde diferentes programas principais como se explica no programa 1.

Programa 1. Factorial mediante unha función.

No programa 2 pódese ver o uso da mesma función,

m / (m - n)! n

paira calcular a expresión a través da fórmula (m / n).

No segundo programa non escribimos o código do factorial e haberá que indicar ao compilador que a función se compilará aparte. Por iso deberase indicar o tipo de factorial, especificando o distintivo extern. Con este esquema, o módulo obxecto que se xera ao compilar a definición da función factorial enlázase co creado polo programa principal obtendo un único programa executable.

Programa 2. Uso 2 da función Factorial.

Como se viu nos exemplos, se utilizamos as funcións nos programas C, podemos facer alusións de tres tipos: definición, chamada e desenvolvemento.

Definición da función

Serve paira expresar o que fai o subprograma, especificando o tipo de resultado da función, o nome, os argumentos, a definición dos argumentos e o corpo.

Se hai máis dun argumento, distínguense polo carácter. No Exemplo 1 o nome da función é factorial, o tipo de resultado é long, o argumento n, a definición do argumento int n, e todo o que está xunto ao corpo até o programa principal. Hai que ter en conta que o programa principal é una función chamada main sen argumento.

O formato da definición é o seguinte:

Se a función devolve resultados, farase a través da sentenza return, que normalmente é a última do corpo. Se a función non devolve resultados (noutras linguaxes chámase procedemento), escribirase como tipo de resultado o void, xa que se non se menciona o tipo de resultado suporase a devolución do número enteiro.

A definición dos argumentos realízase como definición dos datos. A única diferenza é que estes datos sexan enviados desde outras funcións (ou desde o programa principal). Por iso, estes argumentos denomínanse formais e ao chamar á función encheranse con datos concretos.

No corpo da función indícase o código do subprograma, indicando tanto a definición dos seus datos como as instrucións.

Imos escribir a definición que devolve o maior número nos dous números enteiros: inventamos o nome, os grandes, por exemplo, os parámetros son dous e ademais os dous números enteiros (os chamados a e b) e o tipo de resultado é un dos dous números, polo que será ademais enteiro. Por tanto, o xefe da función será:

int grandes (a, b)

int a, b; /*parámetros de función */

O corpo é moi sinxelo e una vez realizado aquí utilizarase a variable local denominada resultado.

1er resultado

/*Variable local*/ if (a b) resultado = a; else resultado = b; return (resultado)

Orzamentos

Chamada da función

Cando se quere executar una función realízase una chamada, de forma que cos datos indicados na chamada (parámetros) execútese o código correspondente á definición da función e devólvese o resultado.

Se a función devolve resultados, a chamada aparecerá normalmente á dereita dunha asignación. Con todo, tamén pode aparecer no medio dunha expresión ou como parámetro doutra función.

Pensemos que lemos dous números nas variables z1 e z2 e queremos escribir o máis grande. Temos dúas opcións:

a) int em; ... em = grandes (z1, z2) printf (“%d”, em); ... b) printf (“%d”, grandes (z1, z2);

No programa 2 descrito inicialmente pódese observar que a función factorial chámase tres veces nun mesmo programa, pero utilizando distintos parámetros.

Cando hai que obter máis dun resultado nun subprograma, non se pode facer con sentenza return (isto permite devolver un único resultado). Isto farase a través dos parámetros definidos con referencia (ver capítulo 10).

Desenvolvemento da función

Cando nun programa chamamos a unha función que está definida noutro módulo, a función debe ser descrita para que por falta de definición o compilador non dea erro. Isto realizouse no Exemplo 2 e o que se debe especificar no informe é: paira indicar que se define externamente a palabra crave extern, paira diferenciar o tipo de resultado, o nome da función e a función ( ). No exemplo que nos ocupa, a explicación sería a seguinte.

extern grandes int ( );

Cando a función e a chamada están dentro dun mesmo módulo, non é necesario realizar o deseño da función, se a definición da función escríbese antes da chamada, senón é necesario o envío pero sen introducir a palabra crave externa.

Macros

Esta ferramenta de programación, tan común nas linguaxes de ensamblaje, aparece nunhas poucas linguaxes de alto nivel. Por exemplo en C.

As macros utilízanse paira definir e referenciar subprogramas simples, pero presentan as seguintes diferenzas funcionais:

  • as chamadas non supoñen a execución do subprograma. Pola contra, o compilador substitúe una chamada ao corpo da definición. Por tanto, durante a compilación as chamadas desaparecerán e se compilará un novo código.
  • os programas executables son máis longos, pero máis rápidos.
  • se non se utilizan paréntese cos parámetros, pode haber problemas.
  • non son apropiados paira subprogramas complexos.

Definir e referenciar (chamar) as macros. O formato da definición é o seguinte:

e o caso do maior fariámolo así:

#define grandes (x, e) ((x) (e)? (x) : (e)

if

en lugar da estrutura, ? : utilizouse a expresión, xa que pola contra non se pode devolver o resultado. As referencias realízanse igual que as chamadas da función, aínda que a maneira de influír é moi diferente.

Con esta referencia,

em = grandes (zenb1, zenb2);

a substitución do compilador en linguaxe máquina dará como resultado:

em = ((zenb1) (zenb2)? (zenb1) : (zenb2)

Así é, porque o compilador ao ver un nomee macro substitúeo polo corpo da macro, substituíndo os argumentos formais por parámetros de referencia.

Como se pode observar, o mecanismo é máis reducido que o das funcións, polo que de cando en cando utilízase.

Paira finalizar, colocaremos una macro paira calcular a superficie do círculo:

#define PI 3.1416

# define superficie (r) PI *(r)*(r)

Babesleak
Eusko Jaurlaritzako Industria, Merkataritza eta Turismo Saila