Anuncios

Bienvenidos sean a este post, hoy veremos como es la intercambiabilidad entre nombres de array y apuntadores.

Anuncios
Anuncios

Con todo lo comentado anteriormente en otros posts ahora podemos enntender de mejor forma como pasar los arrays como argumentos para las funciones, ya que si pasaramos un array por valores en lugar de referenccia con array de tamaño muy grandes podriamos tener serios problemas con la memoria a largo plazo, sin embargo el array no envia su informacion por valor sino por su referencia, y mediante esta referencia es la que usaremos en el cuerpo de la funcion, es decir que siempre usaremos la direccion del elemento cero en lugar de su valor, esto es asi porque C convierte el nombre de la ubicacion del array a un valor de apuntador, &array[0], y este sera lo que realmente usamos en la funcion.

Anuncios

Aqui podemos hablar de su verdadero poder como es la capacidad de intercambiar un nombre de array con un apuntador cuando usamos un nombre de array como un parametro para ser pasado a una funcion, estas son cuatro posibles formas de pasar un array como argumento:

  • Pasar un nombre de array como parametro para luego usar la notacion del array en la funcion
  • Pasar un apuntador de array como parametro y luego usar el apuntador en la funcion
  • Pasar un nombre de array como parametro y luego usarlo como un apuntador en la funcion
  • Pasar un apuntador a un array como un parametro y usar una notacion de array en la funcion
Anuncios

Las que nos pueden resultar mas curiosas son las ultimas dos, para entenderlo un poco mejor vamos a crear un pequeño ejemplo, para ello crearemos un nuevo archivo que llamaremos ejemplo17.c y le agregaremos el siguiente codigo:

ejemplo17.c

#include <stdio.h>

void traversal1(int tam, int arr[])
{
	printf("\n(1) Primer caso: \n\n");
	for(int i=0; i < tam; i++)
	{
		printf("&(array[%1d]) = %#1x, array[%1d] = %1d\n",
			i, (unsigned long)&(arr[i]), i, arr[i]);
	}
}

void traversal2(int tam, int* aArr)
{
	printf("\n(2) Segundo caso: \n\n");
	for(int i=0; i < tam; i++, aArr++)
	{
		printf("aArr = %#1x, *aArr = %1d\n",
			(unsigned long)aArr, *aArr);
	}
}

int main()
{
	const int tamArray = 5;
	int array[] = {1, 2, 3, 4, 5};

	printf("Valores iniciales: \n\n");
	printf("direcccion del array = %#1x, valor de array = %d\n",
		(unsigned long)array, *array);
	printf("direccion de &array[0] = %#1x, valor de array[0] = %d\n",
		(unsigned long)&array[0], array[0]);

	traversal1(tamArray, array);
	traversal2(tamArray, array);

	return 0;
}
Anuncios

Primero hablemos del main, en este caso primero definimos una constante para el tamaño del array, despues un array simple, lo siguiente seran tres lineas para mostrar el valor de memoria e inicial del array de dos formas distintas, luego llamaremos a dos funciones previamente definidas, ccomencemos con la primera funcion.

Anuncios

Esta se llamara trasversal1 y recibira dos argumentos, el primero sera la constante y luego el array directo, despues indicaremos a cual caso corresponde, para luego tener un bucle for que pasara por todos los elementos del array de forma tradicional y mostraremos la direccion de memoria de esa posicion del array y el valor correspondiente.

Anuncios

La siguiente funcion es similar a la descripta anteriormente pero esta usara un apuntador al array como segundo argumento, en este caso usaremos lo visto en el post anterior donde usamos al operador incremental en el bucle para ir pasando por todos los elementos del array por medio del apuntador, volvemos a mostrar los mismos datos que anteriormente, con todo esto comentado podemos pasar a compilarlo y ver como es su salida:

tinchicus@dbn001vrt:~/lenguajes/C$ ./prog/ejemplo17 
Valores iniciales: 

direcccion del array = 0xe52e76d0, valor de array = 1
direccion de &array[0] = 0xe52e76d0, valor de array[0] = 1

(1) Primer caso: 

&(array[0]) = 0xe52e76d0, array[0] = 1
&(array[1]) = 0xe52e76d4, array[1] = 2
&(array[2]) = 0xe52e76d8, array[2] = 3
&(array[3]) = 0xe52e76dc, array[3] = 4
&(array[4]) = 0xe52e76e0, array[4] = 5

(2) Segundo caso: 

aArr = 0xe52e76d0, *aArr = 1
aArr = 0xe52e76d4, *aArr = 2
aArr = 0xe52e76d8, *aArr = 3
aArr = 0xe52e76dc, *aArr = 4
aArr = 0xe52e76e0, *aArr = 5
tinchicus@dbn001vrt:~/lenguajes/C$
Anuncios

Aca podemos ver como todo lo que vimos hasta ahora se aplico perfectamente, ya sea por medio de la forma tradicional como por medio del apuntador y el operador incremental, tomemos el codigo anterior y junto a las otras funciones agreguemos la siguiente:

void traversal3(int tam, int arr[])
{
	printf("\n(3) Tercer caso: \n\n");
	for(int i=0; i < tam; i++, arr++)
	{
		printf("arr = %#1x, *arr = %1d\n",
			(unsigned long)arr, *arr);
	}
}
Anuncios

Aqui veremos el tercer caso de los que mencionamos anteriormente, mostramos el mensaje para indicar que es esto, luego tenemos un bucle for donde aplicaremos el operador incremental al array dado que gracias a la intercambiabilidad entre el array y los apuntadores lo podremos hacer sin ningun inconveniente, en este caso volveremos a mostrar la direccion de memoria de cada elemento y el valor de la posicion, lo siguiente sera agregar el llamado a esta funcion en el main mediante la siguiente linea:

traversal3(tamArray, array);
Anuncios

Con todo esto comentado podemos pasar a compilarlo nuevamente y ver como es su nueva salida:

tinchicus@dbn001vrt:~/lenguajes/C$ ./prog/ejemplo17 
Valores iniciales: 

direcccion del array = 0xe08b2bf0, valor de array = 1
direccion de &array[0] = 0xe08b2bf0, valor de array[0] = 1

(1) Primer caso: 

&(array[0]) = 0xe08b2bf0, array[0] = 1
&(array[1]) = 0xe08b2bf4, array[1] = 2
&(array[2]) = 0xe08b2bf8, array[2] = 3
&(array[3]) = 0xe08b2bfc, array[3] = 4
&(array[4]) = 0xe08b2c00, array[4] = 5

(2) Segundo caso: 

aArr = 0xe08b2bf0, *aArr = 1
aArr = 0xe08b2bf4, *aArr = 2
aArr = 0xe08b2bf8, *aArr = 3
aArr = 0xe08b2bfc, *aArr = 4
aArr = 0xe08b2c00, *aArr = 5

(3) Tercer caso: 

arr = 0xe08b2bf0, *arr = 1
arr = 0xe08b2bf4, *arr = 2
arr = 0xe08b2bf8, *arr = 3
arr = 0xe08b2bfc, *arr = 4
arr = 0xe08b2c00, *arr = 5
tinchicus@dbn001vrt:~/lenguajes/C$
Anuncios

Por ultimo vamos a tomar el codigo nuevamente y agregaremos la siguiente funcion junto con las otras:

void traversal4(int tam, int* aArr)
{
	printf("\n(4) Cuarto caso: \n\n");
	for(int i=0; i < tam; i++)
	{
		printf("&(aArr[%1d]) = %#1x, aArr[%1d] = %1d\n",
			i, (unsigned long)&(aArr[i]), i, aArr[i]);
	}
}
Anuncios

Aqui tenemos el cuarto caso, donde el segundo argumento sera un apuntador del array, observen que usamos el bucle for donde no implementamos el incrementador sobre el apuntador sino que usamos la forma estandar de acceder a los elementos del array por medio del apuntador, tal como vimos en la funcion anterior la intercambiabilidad nos permite poder acceder a los elementos de un array atraves de un apuntador como si fuera un array comun, y al igual que vimos anteriomente debemos agregar el llamado a la funcion en el main mediante la siguiente linea:

traversal4(tamArray, array);
Anuncios

Con todo esto coentado antes de compilarlo veamos como es su codigo final:

ejemplo17.c

#include <stdio.h>

void traversal1(int tam, int arr[])
{
	printf("\n(1) Primer caso: \n\n");
	for(int i=0; i < tam; i++)
	{
		printf("&(array[%1d]) = %#1x, array[%1d] = %1d\n",
			i, (unsigned long)&(arr[i]), i, arr[i]);
	}
}

void traversal2(int tam, int* aArr)
{
	printf("\n(2) Segundo caso: \n\n");
	for(int i=0; i < tam; i++, aArr++)
	{
		printf("aArr = %#1x, *aArr = %1d\n",
			(unsigned long)aArr, *aArr);
	}
}

void traversal3(int tam, int arr[])
{
	printf("\n(3) Tercer caso: \n\n");
	for(int i=0; i < tam; i++, arr++)
	{
		printf("arr = %#1x, *arr = %1d\n",
			(unsigned long)arr, *arr);
	}
}

void traversal4(int tam, int* aArr)
{
	printf("\n(4) Cuarto caso: \n\n");
	for(int i=0; i < tam; i++)
	{
		printf("&(aArr[%1d]) = %#1x, aArr[%1d] = %1d\n",
			i, (unsigned long)&(aArr[i]), i, aArr[i]);
	}
}

int main()
{
	const int tamArray = 5;
	int array[] = {1, 2, 3, 4, 5};

	printf("Valores iniciales: \n\n");
	printf("direcccion del array = %#1x, valor de array = %d\n",
		(unsigned long)array, *array);
	printf("direccion de &array[0] = %#1x, valor de array[0] = %d\n",
		(unsigned long)&array[0], array[0]);

	traversal1(tamArray, array);
	traversal2(tamArray, array);
	traversal3(tamArray, array);
	traversal4(tamArray, array);

	return 0;
}
Anuncios

Ahora si podemos pasar a compilarlo y ver como es su salida:

tinchicus@dbn001vrt:~/lenguajes/C$ ./prog/ejemplo17 
Valores iniciales: 

direcccion del array = 0x3a7fe4f0, valor de array = 1
direccion de &array[0] = 0x3a7fe4f0, valor de array[0] = 1

(1) Primer caso: 

&(array[0]) = 0x3a7fe4f0, array[0] = 1
&(array[1]) = 0x3a7fe4f4, array[1] = 2
&(array[2]) = 0x3a7fe4f8, array[2] = 3
&(array[3]) = 0x3a7fe4fc, array[3] = 4
&(array[4]) = 0x3a7fe500, array[4] = 5

(2) Segundo caso: 

aArr = 0x3a7fe4f0, *aArr = 1
aArr = 0x3a7fe4f4, *aArr = 2
aArr = 0x3a7fe4f8, *aArr = 3
aArr = 0x3a7fe4fc, *aArr = 4
aArr = 0x3a7fe500, *aArr = 5

(3) Tercer caso: 

arr = 0x3a7fe4f0, *arr = 1
arr = 0x3a7fe4f4, *arr = 2
arr = 0x3a7fe4f8, *arr = 3
arr = 0x3a7fe4fc, *arr = 4
arr = 0x3a7fe500, *arr = 5

(4) Cuarto caso: 

&(aArr[0]) = 0x3a7fe4f0, aArr[0] = 1
&(aArr[1]) = 0x3a7fe4f4, aArr[1] = 2
&(aArr[2]) = 0x3a7fe4f8, aArr[2] = 3
&(aArr[3]) = 0x3a7fe4fc, aArr[3] = 4
&(aArr[4]) = 0x3a7fe500, aArr[4] = 5
tinchicus@dbn001vrt:~/lenguajes/C$
Anuncios

Con esto tenemos mas claro a que nos referimos con la intercambiabilidad entre nombres de array y apuntadores de array, no existe una regla o buena practica, simplemente queda a criterio de cada uno como quieran usarlo y como les resulte mas practico a la hora de visualizar el codigo.

Anuncios

En resumen, hoy hemos visto la intercambiabilidad entre nombres de array y apuntadores de estos, como es, cuales son las posibles, como esto es gracias a la forma de trabajar del array de lo cual hablamos en posts anteriores pero ahora lo tenemos aplicado en la practica, espero les haya sido de utilidad sigueme en tumblr, Twitter o Facebook para recibir una notificacion cada vez que subo un nuevo post en este blog, nos vemos en el proximo post.

Anuncios
pp258

Donación

Es para mantenimento del sitio, gracias!

$1.50