[Utu-emt-prog2-info] clase 3 "Ámbito de las variables" y "Anidamiento de funciones"

Federico Kouyoumdjian fedekp en autistici.org
Vie Jul 15 18:39:50 CEST 2011


fuente: 
http://www.etnassoft.com/biblioteca/introduccion-al-desarrollo-de-software/ 
y producción propia

2.12.2. Ámbito de las variables

El ámbito de las variables hace referencia a las partes del programa que 
las pueden emplear. Dicho de otra manera, el ámbito de las variables 
abarca todas aquellas instrucciones que pueden acceder a ellas.

En el código de una función se pueden emplear todas las variables 
globales (las que son “visibles” por cualquier instrucción del 
programa), todos los parámetros formales (las variables que equivalen a 
los argumentos de la función), y todas las variables locales (las que se 
declaran dentro del cuerpo de la función).

En algunos casos puede no ser conveniente utilizar variables globales, 
pues dificultarían la compresión del código fuente, cosa que 
dificultaría el posterior depurado y mantenimiento del programa. Para 
ilustrarlo, veamos el siguiente ejemplo:

#include <stdio.h>
unsigned int A, B;
void reduce( void )
{
	if( A < B )
		B = B - A;
	else
		A = A - B;
} /* reduce */

void main( void )
{
	printf( "El MCD de: " );
	scanf( "%u%u", &A, &B );
	while( A!=0 && B!=0 )
		reduce();
	printf( "... es %u\n", A + B );
} /* main */

Aunque el programa mostrado tiene un funcionamiento correcto, no es 
posible deducir directamente qué hace la función reduce(), ni tampoco 
determinar de qué variables depende ni a cuáles afecta. Por tanto, hay 
que adoptar como norma que ninguna función dependa o afecte a variables 
globales. De ahí el hecho de que, en C, todo el código se distribuye en 
funciones, se deduce fácilmente que no debe haber ninguna variable global.

Así pues, todas las variables son de ámbito local (parámetros formales y 
variables locales). En otras palabras, se declaran en el entorno local 
de una función y sólo pueden ser empleadas por las instrucciones dentro 
de la misma.

Las variables locales se crean en el momento en que se activa la función 
correspondiente, es decir, después de ejecutar la instrucción de llamada 
de la función. Por este motivo, tienen una clase de almacenamiento 
denominada automática, ya que son creadas y destruidas de forma 
automática en el procedimiento de llamada a función.

Anidamiento de funciones

El anidamiento de funciones se refiere a la posibilidad de que una 
función esté definida dentro de otra función. El anidamiento se puede 
dar en varios niveles (una función func1 dentro de otra func2, func2 
dentro de func3, y así sucesivamente). El anidamiento de funciones se 
permite en C pero no se permite en C++.
En el siguiente ejemplo la función resta5 está anidada en suma10 :

#include <stdio.h>
int suma10 (int a)
{
	int b=15;
	void resta5()
	{
		b=b-5;
	}
	resta5();
	return a+b;
}
int main()
{
	int c=30;
	int d=suma10(c);
	printf("suma10(30)=%d\n",d);
	return 0;
}

En este ejemplo se puede llamar a resta5 desde suma10 pero no se la 
puede llamar desde main ya que la única función que está en el ámbito de 
main es suma10 y todas las funciones que se declaran en stdio.h.
Notar que una adecuada sangría nos permite visualizar mejor qué 
funciones son invocables desde la función en la que estemos parados. Las 
funciones que están a un mismo nivel o adentro de la función que se está 
definiendo son invocables, el resto no.
Para el caso del ámbito de las variables: desde main se puede acceder a 
las variables c y d pero no se puede acceder ni a a ni a b. Desde suma10 
se puede acceder a a y a b pero no se puede acceder ni a c ni a d.
En la función suma10 se define resta5 y por lo tanto se puede acceder a 
la misma. Hay que notar que en resta5 se accede a una variable que no 
está declarada en resta5. Esta es una mala práctica de programación. Lo 
más correcto hubiera sido que si se quería modificar el valor de b se 
definiera resta5 de la siguiente manera:

void resta5(int * x)
{
	*x= *x - 5;
}
y se la invocara de la siguiente manera:

resta5(&b);

En esta segunda versión de resta5 se recibe la dirección de memoria de 
la variable a modificar, se resta 5 a lo apuntado por dicha dirección de 
memoria, y el resultado de dicha resta se lo asigna a lo apuntado por la 
dirección de memoria recibida por parámetro.



Más información sobre la lista de distribución Utu-emt-prog2-info