30 - Vectores y punteros


Vectores de tipo numérico.

Cuando definimos un vector, por ejemplo:

    int vec[3];
    vec[0]=10;
    vec[1]=50;
    vec[2]=100;

lo que estamos definiendo es un puntero que reserva espacio para 3 componentes de tipo entero, guardando la dirección del primer elemento. Esto sucede en memoria (suponiendo que un tipo int ocupa 4 bytes):

        Dir. de Mem.	Contenido	Nombre de variable
        1000		1004		vec
        1004		10		[0]
        1008		50		[1]
        1012		100		[2]

Cuando accedemos a una componente en particular del vector, calcula la dirección correspondiente de la siguiente manera: dirección del puntero + (bytes que ocupa según tipo de dato * subíndice)

Suma a la dirección que almacena, que es la del primer elemento, los bytes según el tipo de dato * subíndice indicado.
Para ejecutar esta línea:

    cout<<x[0];

encuentra la dirección de la componente 0 utilizando el cálculo anterior: 1004 + (4*0), o sea 1004.

Para encontrar la dirección de la componente subíndice 2: 1004 + (4 * 2), o sea 1012.

Ejemplo:

Si definimos un vector de tipo float:

	float vec[5];

estamos definiendo es un puntero que reserva espacio para 5 componentes de tipo real (float). Esto sucede en memoria (suponiendo que un float ocupa 4 bytes):

	Dir. de Mem.	Contenido	Nombre de variable
	1000		1004		vec
	1004				[0]
	1008				[1]
	1012				[2]
	1016				[3]
	1020				[4]

Cuando cargamos las componentes encuentra las direcciones de cada componente realizando los siguientes cálculos:

	cin >>x[0];	// 1004 + (4 *0), o sea 1004.
	cin >>x[1];	// 1004 + (4 *1), o sea 1008.
	cin >>x[2];	// 1004 + (4 *2), o sea 1012.
	cin >>x[3];	// 1004 + (4 *3), o sea 1016.
	cin >>x[4];	// 1004 + (4 *4), o sea 1020.

Vectores de caracteres.

Cuando definimos un vector de caracteres, por ejemplo:

    char cadena[10];

lo que estamos definiendo es un puntero que reserva espacio para 10 componentes de tipo char, guardando la dirección del primer elemento, el cero. Esto sucede en memoria:

	Dir. de Mem.	Contenido	Nombre de variable
	1000		1004		Cadena
	1004				[0]
	1005				[1]
	1006				[2]
	1007				[3]
	1008				[4]
	1009				[5]
	1010				[6]
	1011				[7]
	1012				[8]
	1013				[9]

Cuando cargamos la cadena con:

    strcpy_s(Cadena, 10, "Hola");

busca la dirección del puntero (1004) y comienza a cargar los caracteres, cuando la cadena finaliza, agrega el terminador de cadena. En memoria:

	Dir. de Mem.	Contenido	Nombre de variable
	1000		1004		Cadena
	1004		'H'		[0]
	1005		'o'		[1]
	1006		'l'		[2]
	1007		'a'		[3]
	1008		'\0'		[4]
	1009				[5]
	1010				[6]
	1011				[7]
	1012				[8]
	1013				[9]

Impresión de cadenas

Cuando imprimimos un vector de caracteres:

	cout<<Cadena;	// imprime Hola

no necesitamos indicar el subíndice pues busca la dirección de cadena (1004) y recorre los siguientes bytes imprimiendo cada carácter hasta encontrar el terminador de cadena.

Ejemplo:

char cad[20];
strcpy_s(cad,20,"Programar");
cout<<cad;		// imprime Programar
cout<<cad[0];		// imprime P
cout<<cad[6];		// imprime m

Cuando solicitamos la impresión de la componente 5, encuentra la dirección de dicha componente utilizando el cálculo visto anteriormente: dirección del vector + (bytes según tipo de dato *subíndice). El tipo de dato char ocupan normalmente 1 bytes.

Punteros a char

Carga e impresión

Ejemplo:

char cad[10];
strcpy_s(cad,10,"Sol");
char *pc;
pc=cad;
cout<<pc;

Seguimiento del ejemplo:

- Definimos un vector de caracteres: char cad[10];

	Dir. de Mem.	Contenido	Nombre de variable
	1000		1004		cad
	1004				[0]
	1005				[1]
	1006				[2]
	1007				[3]
	1008				[4]
	1009				[5]
	1010				[6]
	1011				[7]
	1012				[8]
	1013				[9]

- Cargamos el vector: strcpy_s(cad,10,"Sol");

	Dir. de Mem.	Contenido	Nombre de variable
	1000		1004		cad
	1004		'S'		[0]
	1005		'o'		[1]
	1006		'l'		[2]
	1007		'\0'		[3]
	1008				[4]
	1009				[5]
	1010				[6]
	1011				[7]
	1012				[8]
	1013				[9]

- Definimos un puntero a char: char *pc;

	Dir. de Mem.	Contenido	Nombre de variable
	1000		1004		cad
	1004		'S'		[0]
	1005		'o'		[1]
	1006		'l'		[2]
	1007		'\0'		[3]
	1008				[4]
	1009				[5]
	1010				[6]
	1011				[7]
	1012				[8]
	1013				[9]
	1014				pc

- Asignamos al puntero pc la cadena: pc=cad;

	Dir. de Mem.	Contenido	Nombre de variable
	1000		1004		cad
	1004		'S'		[0]
	1005		'o'		[1]
	1006		'l'		[2]
	1007		'\0'		[3]
	1008				[4]
	1009				[5]
	1010				[6]
	1011				[7]
	1012				[8]
	1013				[9]
	1014		1004		pc

Cuando asignamos a un puntero a char una cadena, no antecedemos a cad el símbolo & porque cad contiene una dirección. Tampoco antecedemos el asterisco * antes de pc. Estamos manejando direcciones.

- Imprimimos donde apunta el puntero: cout<<Pc;

Retornar