FUNCIONES (cont.)

VARIABLES DE TIPO STATIC

Las variables de tipo static son variables permanentes que se encuentran dentro de una función o de un archivo fuente. Se diferencian de las variables globales en que no pueden verse desde el exterior del bloque o del archivo donde fueron declaradas. Sin embargo (a diferencia de las auto variables) conservan su existencia así como su valor fuera del bloque o del archivo de su declaración.

VARIABLES LOCALES DE TIPO STATIC

Cuando se aplica el modificador static a una variable local, el compilador asigna a esta un área de memoria permanente, exactamente como sucede con una variable global. La diferencia fundamental entre las dos es que la variable local static solo puede ser vista desde el interior del bloque donde ha sido declarada. Se trata de una variable local que mantiene el propio valor entre una llamada y otra.

 

  • #include <stdio.h>
    int serie(void);
    void main()
  • {

  • int i;
    for (i=0;i<10;i++)printf("\n %d", serie());
  • }
 
  • int serie(void)
  • {

  • static int serie_num;
    return(serie_num++);
  • }
 

En este ejemplo, la variable serie_num sigue existiendo entre una llamada y otra. Contrariamente a lo que sucede a una variable local normal (auto variable). Esto significa que cada llamada a la función serie() puede retornar un número nuevo en base al último generado.

VARIABLES GLOBALES DE TIPO STATIC

Aplicando el especificador static a una variable global el compilador crea una variable global cuya validez se extiende solo a las funciones definidas dentro del archivo donde dicha variable fue declarada.

 

  • #include <stdio.h>
    /* File "serie_n.cpp"
    */
    static int serie_num;
    int serie(void);
    void main()
  • {

  • int i;
    for (i=0;i<10;i++)printf("\n %d", serie());
  • }
 
  • int serie(void)
  • {

  • return(serie_num++);
  • }
 
  • /* File "inital.cpp"
    */
    extern serie_num; /* Error en este archivo la variable serie_num no tiene validez*/
    void init_num(void)

  • serie_num=100;
 

La variable global static serie_num solo tiene validez en el archivo en que se encuentra ("serie_n.cpp"). Sería un error utilizarla en el archivo"inital.cpp".

PARAMETROS Y ARGUMENTOS

En general existen dos modos para pasar argumentos a una función. El primero es lo que se llama llamada por valor (call by value). El segundo es la llamada por referencia (call by reference).

LLAMADA POR VALOR

La llamada por valor copia el valor de un argumento en el parámetro formal de la función. Ello consigue que eventuales modificaciones de dicho parámetro dentro de la función no tenga ningún efecto sobre la variable utilizada para ser pasada a la función.

 

  • #include <stdio.h>
    long int cuadrado(long int x);
    main()
  • {

  • long int i=20;
    printf("\n %ld = %ld^2",cuadrado(i),i);
    return 0;
  • }
 

  • long int cuadrado(long int x)
  • {

  • x=x*x;
    return x;
  • }
 

En este ejemplo, el valor del argumento de cuadrado(), 20, es copiado en el parámetro x. Cuando tiene lugar la asignación x=x*x, el único elemento modificado es la variable local x, mientras la variable i utilizada para llamar a cuadrado(), mantiene su valor original 20. La visualización sería: 400=20^2.

LLAMADA POR REFERENCIA

En este caso es la dirección (puntero, en inglés pointer) del argumento lo que se copia en el parámetro. En el interior de la función dicho puntero permite acceder al argumento utilizado en la llamada. Esto significa que todo cambio aportada al parámetro incide sobre la variable utilizada para llamar a la función.
Los punteros en una función son pasados como cualquier otro valor. Obviamente es necesario que los parámetros sean declarados de tipo puntero (pointer).

 

  • #include <stdio.h>
    void intercambia(int *x,int *y);
    void main()
  • {

  • int x=10,y=20;
    printf("\n x inicial = %-d ,y inicial = %-d",x,y);
    intercambia(&x,&y);
    printf("\n x final = %-d ,y final = %-d",x,y);
  • }
 
  • void intercambia(int *x,int *y)
  • {

  • int temp;
    temp=*x;
    *x=*y;
    *y=temp;
  • }
 

En este ejemplo se asigna el valor 10 a la variable x y 20 a la variable y. Esto se consigue con la llamada a intercambia() con la dirección de las variables x e y.Para obtener dichas direcciones se aplica el operador unario &.

LLAMADA DE FUNCIONES CON VECTORES

Cuando se utiliza como argumento un vector para llamar a una función se le pasa la dirección de dicho vector y no una copia de del mismo. La dirección de un vector es un puntero su primer elemento.

 

  • #include <stdio.h>
    #define N 10 /* N es una constante de valor 10 */
    void minimo(int x[], int n, int *min);
    void main()
  • {

  • int k[N],i,m;/*k es un vector de dimesión 10 (N vale 10) */
    for (i=0;i<N;i++) /* entrada de datos */
    {

  • printf("\n k[%1d]? ",i);
    scanf("%d",&k[i]);
  • {
    minimo(k,N,&m);
    printf("\n minimo = %-d",m);
  • }
 
  • void minimo(int x[],int n, int *min)
  • {

  • int i,tmin;
    tmin=x[0];
    for(i=1;i<n;i++)if(x[i]<tmin)tmin=x[i];
    *min=tmin;
  • }
 

El vector k es pasado a la función minimo() como un puntero a un valor de tipo entero. Dado que el lenguaje C no prevé el control sobre el límite de los vectores, las dimensiones reales del mismo son irrelevantes para el parámetro (aunque naturalmente no para el programa).
La función minimo se podría haber declarado:

  • void minimo(int *k,n,int min);

Quiere decir que está permitido atribuir a todo puntero un índice con [], como si se tratara de un vector.

FUNCIONES QUE RETORNAN UN PUNTERO

Las funciones que retornan un puntero son gestionadas como las otras En el ejemplo que sigue la función retorna un puntero a un string.

 

  • #include <stdio.h>
    char *error_msg(int num_error);
    void main()
  • {

  • printf("\n %s",error_msg(24));
  • }
 

  • char *error_msg(int n)
  • {

  • /* Vector de strings*/
    static char *message[]=

  • "O.K.",
    "Error de apertura",
    "Error de lectura",
    "Error de escritura",
    "Error de cierre",
    "Este error no existe"

  • if(n>5 || n<0)n=5;
    return message[n];
  • }