Ing. Informática Programación I Bloque 8 La descomposición funcional y el diseño descendente (II) Bloque 8 Ing. Informática Programación I Bloque 8 Paso de parámetros por referencia Cómo escribir una función que modifique los valores de los parámetros de llamada? Ejemplo: una función que intercambie los valores de dos variables Ing. Informática Programación I Bloque 8 Paso de parámetros por referencia void intercambia(int a, int b) { int c; c=a; a=b; b=c; } main() { int x=3,y=5; intercambia(x,y); ... } Problema: los parámetros se pasan por valor: los valores 3 y 5 se copian en los parámetros a y b. Al acabar la llamada las variables x e y no han cambiado su valor Ing. Informática Programación I Bloque 8 Paso de parámetros por referencia Solución: Pasar como parámetro la dirección donde se encuentra la variable (un puntero) Lo que se copia es la dirección, no el valor de la variable Esto permite que la función pueda acceder al valor que hay en esa dirección y modificarlo Nota: lo que no tendría efecto sería hacer que el parámetro formal apuntase a otra dirección (ya que sólo trabaja con una copia de la dirección) Ing. Informática Programación I Bloque 8 Paso de parámetros por referencia Solución: void intercambia(int *a, int *b) { int c; c=*a; *a=*b; *b=c; } main() { int x=3,y=5; intercambia(&x,&y); ... } Ing. Informática Programación I Bloque 8 Paso de parámetros por referencia Ejemplo: main() { #include <stdio.h> long int factorial(int n) { int i; long int f=1; for (i=n;i>=2;i--) f=f*i; return f; } } long int combinatori(int m, int n) { return factorial(m)/(factorial(n)*factorial(m-n)); } void escriu_resultat(int m, int n, int c) { printf("%d sobre %d val %d\n",m,n,c); } int m,n,c; llegir_nombres(&m, &n); c=combinatori(m,n); escriu_resultat(m,n,c); void llegir_nombres(int *m, int *n) { printf("CALCULO DEL COMBINATORIO m sobre n\n"); printf("Introduce m: "); scanf("%d",m); //notad que no está el & (porque ya es una dirección) printf("Introduce n: "); scanf("%d",n); //notad que no está el & (porque ya es una dirección) } Ing. Informática Programación I Bloque 8 Paso de arrays Como se ha visto en el bloque 7, un array (o un string) es internamente un puntero a una zona de memoria donde están los valores Cuando se pasa un array por parámetro no se copian todos los valores, sólo se pasa la dirección (paso por referencia) Ing. Informática Programación I Paso de arrays Ejemplo: void intercambia(int a[2]) { int c; c=a[0]; a[0]=a[1]; a[1]=c; } main() { int A[2]={3,5}; intercambia(A); ... } Bloque 8 Ing. Informática Programación I Paso de arrays Suelen representarse los parámetros como punteros: void intercambia(int *a) { int c; c=*a; *a=*(a+1); *(a+1)=c; } main() { int A[2]={3,5}; intercambia(A); ... } Bloque 8 Ing. Informática Programación I Bloque 8 Paso de estructuras Si hay que modificar los campos de una estructura, hay que pasarla por referencia (un puntero a la estructura), y no por valor Ejemplo: struct ColorRGB{ short int R; short int G; short int B; }; void funcion(struct ColorRGB *col) { ... } Ing. Informática Ejemplo: Programación I Bloque 8 Paso de estructuras struct ColorRGB{ short int R; short int G; short int B; }; void ompleColor(struct ColorRGB *col) { printf("Introdueix el valor vermell: "); scanf("%d",&((*col).R)); printf("Introdueix el valor verd: "); scanf("%d",&((*col).G)); printf("Introdueix el valor blau: "); scanf("%d",&((*col).B)); } void main() { struct ColorRGB col; ompleColor(&col); //se pasa la dirección de la estructura ... } Ing. Informática Programación I Bloque 8 Paso de estructuras Recordatorio: para acceder a los campos de una estructura apuntada por un puntero suele usarse el operador -> Ejemplo: void ompleColor(struct ColorRGB *col) { printf("Introdueix el valor vermell: "); scanf("%d",&(col->R)); printf("Introdueix el valor verd: "); scanf("%d",&(col->G)); printf("Introdueix el valor blau: "); scanf("%d",&(col->B)); } Ing. Informática Programación I Retornando una estructura Ejemplo: struct ColorRGB creaColor() /* la función retorna una estructura ColorRGB */ { struct ColorRGB *c; c=(struct ColorRGB *)malloc(sizeof(struct ColorRGB)); printf("Introdueix el valor vermell: "); scanf("%d",&(c->R)); //o scanf("%d",&((*c).R)); printf("Introdueix el valor verd: "); scanf("%d",&(c->G)); //o scanf("%d",&((*c).G)); printf("Introdueix el valor blau: "); scanf("%d",&(c->B)); //o scanf("%d",&((*c).B)); return *c; //retorna la estructura apuntada por el punter c } Bloque 8 Ing. Informática Programación I Visibilidad: ámbito Llamamos ámbito de un elemento (variable, constante, tipo definido por el usuario...) al área donde es visible, donde puede ser accedido En principio, en la función donde se ha declarado Nunca puede haber dos elementos declarados con el mismo nombre en el mismo ámbito Pero sí en ámbitos (funciones) diferentes Bloque 8 Ing. Informática Programación I Bloque 8 Visibilidad: declaraciones globales También se pueden declarar elementos globales, visibles desde cualquier función del programa Se declaran al principio del programa, antes de cualquier función: int x; //x es una variable global // que es visible en f y en main void f() { x=5; } void main() { x=3; f(); } Ing. Informática Programación I Reglas de visibilidad Si hubiese una variable local en una función con el mismo nombre que una variable global, sólo será visible la local: int x; //x es una variable global // que es visible en f y en main void f() { int x; x=5; //aquí se modifica la x local de f ... } void main() { x=3; //aquí se modifica la x global f(); } Bloque 8 Ing. Informática Programación I Efecto lateral El hecho de declarar variables globales dificulta el poder reutilizar las funciones en otros programas el seguimiento del flujo del programa (especialmente si hay varios programadores) Este problema se denomina el efecto lateral Conclusión: por lo general, evitar el uso de variables globales y utilizar en su lugar parámetros Bloque 8 Ing. Informática Programación I Preprocesador El preprocesador es una herramienta que reconoce una serie de instrucciones (directivas del preprocesador), que comienzan por # El preprocesador modifica el código antes de compilar Ejemplos: #define #include Bloque 8 Ing. Informática Programación I Bloque 8 Librerías estándar stdio.h: printf, scanf, gets, puts... string.h: strlen, strcpy, strcat, strcmp,... math.h: incorpora diversas funciones matemáticas como el sino, cosino, tangente (y otras trigonométricas), exponencial,... time.h: funciones de fecha y hora ctype.h: funciones relacionadas con caracteres, como pasar a mayúsculas (toupper) o minúsculas (tolower) stdlib.h: la libreria estándar de C con funciones diversas como malloc, free, abs, atoi, atof,...