Introducción a los Arreglos y Punteros Mag.,Esp.,Lic. Mariano Méndez Correcciones: Ignacio Jordan Facultad De Ingenierı́a - Universidad de Buenos Aires 1 Punteros: Un Cuco... pero no tanto Como se ha comentado anteriormente una variable es un espacio de memoria que se identifica mediante un nombre o identificador único por el cual se hace referencia a ella. Ampliando un poco más este concepto, podemos decir que en realidad la memoria está estructurada como un conjunto de celdas distribuidas linealmente, cada una de estas celdas posee una dirección única dentro de este conjunto, esta dirección se denomina dirección de memoria ver Figura 2. El nombre de una variable es el equivalente humano de la dirección de memoria, ya que serı́a humanamente muy complejo escribir programas complejos y largos que referencien directamente a las direcciones de memoria (Cómo se hacı́a con las primeras computadores), por ello, se utilizan nombres que posteriormente el compilador reemplaza por direcciones de memoria. En muchos lenguajes de programación existe un tipo de dato que almacena exclusivamente direcciones de memoria, este tipo de dato se denomina puntero, ver Figura 1. Cabe destacar que la utilización de punteros agrega un nivel de complejidad al programa que se está desarrollando, ya que el programador, en el caso de C, debe controlar su uso. Como con todos los tipos de datos en C se puede declarar una variable tipo puntero. En el caso especı́fico de los punteros, la declaración se realiza de la siguiente forma: tipoDeDatoAlQueApuntar ∗ NombreDelPuntero ; Concretamente : int double char float 1.1 ∗ ptrEntero ; ∗ prtDouble ; ∗ ptrChar ; ∗ ptrFloat ; //un //un //un //un puntero puntero puntero puntero a a a a un un un un entero double caracter float Operador de Dirección El operador de dirección es un operador unario en C que devuelve la dirección del operando, este corresponde a “&”. int int unEntero =2; ∗ ptrEntero ; p t r E n t e r o= &unEntero ; //un p u n t e r o a un e n t e r o 2 Algoritmos y Programacón I - 75.40 - Cat. Garcia 123 unaVariable unPuntero Fig. 1. Esquema del concepto de Puntero p ... c ... Fig. 2. Esquema de distribución de la memoria ... Introducción a los Arreglos y Punteros 3 En el código escrito anteriormente se definen dos variables, una entera y otra que es un puntero a un entero. En la asignación, el operador de dirección le asigna la dirección de memoria en la cual esta definida la variable unEntero a ptrEntero. 2 unEntero / f2c4 f2c4 ptrEntero Fig. 3. Diagrama del ejemplo 1.2 Operador de Indirección El operador de indirección devuelve el valor del objeto hacia el cual su operando apunta, dicho operando debe ser un puntero. int int unEntero =2; ∗ ptrEntero ; //un p u n t e r o a un e n t e r o p t r E n t e r o= &unEntero ; p r i n t f ( ”d” , ∗ p t r E n t e r o ) ; Cuanto deberı́a mostrar el código anterior? La respuesta correcta es 2. Veamos otro ejemplo #i n c l u s e <s t d i o . h> int main ( ) { int unEntero ; int ∗ ptrUnEntero ; unEntero =7; ptrUnEntero=&unEntero ; p r i n t f ( ”La d i r e c c i o n de memoria de unEntero e s %p \n” ,&UnEntero ) ; 4 Algoritmos y Programacón I - 75.40 - Cat. Garcia p r i n t f ( ” e l v a l o r de p t r U n e n t e r o e s %p\n” , ptrUnEntero ) ; p r i n t f ( ” El v a l o r de unEntero e s %d \n” , UnEntero ) ; p r i n t f ( ” e l v a l o r d e l a d i r e c c i o n de memoria apuntada por p t r U n e n t e r o e return 0 ; } 2 Pasaje de parámetros por referencia Se ha explicado que en C sólo es posible pasar los parámetros por valor, y esta afirmación sigue siendo verdadera, entonces cómo se hace cuando se necesita pasar algún parámetro y que cualquier modificación hecha en la función que recibe el parámetro se vea plasmada o reflejada en la función llamadora, es decir pasar el parámetro por referencia. En C es posible utilizando el concepto de puntero. Si implementamos la siguiente función de intercambio de dos enteros: #i n c l u s e <s t d i o . h> void i n t e r c a m b i o ( int v a l o r 1 , int v a l o r 2 ) { int aux ; aux = v a l o r 1 ; v a l o r 1=v a l o r 2 ; v a l o r 2=aux ; } int main ( ) { int unNumero , otroNumero ; unNumero=1; otroNumero =2; i n t e r c a m b i o ( unNumero , otroNumero ) ; p r i n t f ( ”unNumero = %d \n otroNumero=%d” , unNumero , otroNumero ) ; return 0 ; } tras compilar y ejecutar el programa propuesto, veremos sin asombro que el los valores impreso es : unNumero=1 otroNumero=2 Introducción a los Arreglos y Punteros 5 Ahora bien, ¿Cómo se plantea el programa si realmente se quiere intercambiar los valores de las variables? En realidad para que el pasaje de parámetros resulte por referencia, se debe implementar la función intercambio() de la siguiente forma: void i n t e r c a m b i o ( int ∗ v a l o r 1 , int ∗ v a l o r 2 ) { int aux ; aux = ∗ v a l o r 1 ; ∗ v a l o r 1 =∗ v a l o r 2 ; ∗ v a l o r 2=aux ; } y la llamada a la función debe realizarse : i n t e r c a m b i o (&unNumero,& otroNumero ) ; } Es decir, los parámetros formales de la función son punteros a dos enteros, y los parámetros actuales de la llamada son las direcciones de memoria de las variables que se desea pasar por referencia. En la Figura 3 Constantes Una constante no es nada más que una versión escrita o nombrada de un determinado valor que se utiliza en el programa. En ANSI C se pueden definir valores constantes mediante la utilización de la palabra reservada const de la siguiente forma: int const Pi = 3 . 1 4 1 6 ; const int Base =2; ¿Para qué sirve utilizar constantes si podemos escribir el valor por todo el programa? De hecho no es necesario usar constantes, pues los valores escritos directamente en el programa pueden ir tranquilamente. La utilización de constantes es una práctica de buena programación, por dos motivos: 1. Hacen más fácil la aplicación de cambios al programa. 2. Hacen más comprensible y auto-descriptivo el código fuente. 3. Ayudan al mantenimiento del código fuente. Otra forma de definir valores constantes, es mediante el uso del preprocesador de C. Es posible utilizar la directiva #define, a diferencia de utilizar la palabra reservada el preprocedador de C reemplazará el valor de la directiva por el nombre asignado. #define TRUE 1 #define FALSE 0 6 Algoritmos y Programacón I - 75.40 - Cat. Garcia en el llamador: main unNumero otroNumero valor2 valor1 en intercambio: Fig. 4. Diagrama ejemplo de pasaje de parámetros por referencia Introducción a los Arreglos y Punteros 7 .... .... i f ( esPrimo==TRUE) . . . 4 Vectores ANSI C proporciona un tipo de dato estructurado capaz de almacenar una colección secuencial y finita de de elementos del mismo tipo de dato. A este tipo de dato se lo denomina arreglo o vector unidimensional. La idea detrás de los vectores consiste en que en vez de declarar n variables, por ejemplo, medicion1, medicion2,medicion3, hasta medicion99 se declare una única variable llamada mediciones, que pueda almacenar todos los valores que sean necesarios (cuando se refiere a todos los valores necesarios no hay que olvidar que este valor DEBE ser finito), ver Figura 5. Una vez declarada la variable de tipo vector, se podrán acceder a sus elementos mediante la utilización de un subı́ndice que corresponde a i-ésimo elemento del vector. Para declarar un vector en C, el programador debe especificar el tipo de dato de los componente el vector (por definición, todos son del mismo tipo) y el número de elementos del vector o tamaño: t i p o NombreDelVector [ tama ñoDelVector ] ; Algunos ejemplo de declaraciones de vectores : int main ( ) { int const CANTIDAD MAXIMA TEMP=50; int const DIAS DEL MES=31; int const MESE DEL ANIO=12; int m e d i c i o n e s [ 6 ] ; // v e c t o r de 6 e l e m e n t o s e n t e r o s f l o a t t e m p e r a t u r a s [CANTIDAD MAXIMA TEMP ] ; f l o a t t e m p e r a t u r a s D i a r i a s [ MESE DEL ANIO ] ; char p a l a b r a [ 1 2 ] ; // v e c t o r de 12 c a r a c t e r e s } Nota:Las operaciones entre vectores deben hacerse elemento por elemento. No es posible en C poder asignar un vector a otro, ni sumar un escalar a un vector en forma automática. Nota2: Los vectores se definen con una longitud fija y finita que NO PUEDE SER CAMBIADA a lo largo del programa. 8 Algoritmos y Programacón I - 75.40 - Cat. Garcia int mediciones[6]; mediciones[0] elemento 1 mediciones[1] mediciones[2] mediciones[3] mediciones[4] mediciones[5] elemento 2 elemento 3 elemento 4 elemento 5 elemento 6 Fig. 5. Vector de 6 elementos enteros Nota3: Los vectores o arreglos de caracteres se denominan String y en C tiene un tratamiento especial. Nota4: Los vectores en C al igual que muchos tipos de variables pueden inicializarse en la misma linea en donde se declaran, para ello es necesario enumerar uno a uno los elemento del vector: int m e d i c i o n e s [ 6 ] = { 1 2 , 2 3 , 3 4 , 4 5 , 5 6 , 67 } ; Caso especial 1, inicialización de todos los elementos de un vector con el mismo valor: int m e d i c i o n e s [ 6 ] = { 0 } ; ado que en C, si la lista de inicializadores es menor a la cantidad total de elementos del vector, aquellos elementos que no tengan inicializador serán automáticamente inicializados en 0. Ojo!!, este tipo de reglas no es igual en todos los lenguajes de programación, por lo tanto se desaconseja utilizarla. Caso especial 2, inicialización de un arreglo al que no se le ha definido longitud: int l i s t D e E n t e r o s [ ] = { 5 , 4 , 3 , 2 , 1 } ; En este caso el arreglo tomará la longitud, fija, de la cantidad de elementos con inicializadores, en este caso la longitud será 5. 4.1 Arreglos multidimensionales La primera aproximación a un arreglo multidimensional la tenemos en el concepto algebraico de matriz, en la Figura 6 puede observarse el concepto matemático dibujado a la izquierda y la representación computacional dibujada a la derecha. La declaración de un arreglo bidimensional en este caso se realiza como se describe a continuación: int m a t r i z [ 3 ] [ 3 ] ; Introducción a los Arreglos y Punteros 9 a11 a12 a13 a21 a22 a23 a31 a23 a33 a[0, 0] a[0, 1] a[0, 2] a[1, 0] a[1, 1] a[1, 2] a[2, 0] a[2, 1] a[2, 2] Fig. 6. Una matriz de 3 filas y 3 columnas Cabe destacar que para acceder al contenido de un elemento del arreglo bidimensional, necesitamos dos coordenadas i,j. Por ejemplo, si se desea imprimir el valor almacenado en la fina 2 columna 3 de la matriz, se deberá escribir: p r i n t f ( ”%d” , m a t r i z [ 1 , 2 ] ) ; Ası́ mismo también las matrices pueden ser inicializadas en su declaración : int {0 , {4 , {8 , }; matriz [ 3 ] [ 4 ] 1 , 2 , 3} , 5 , 6 , 7} , 9 , 1 0 , 11} = { /∗ i n i t i a l i z e r s f o r row i n d e x e d by 0 ∗/ /∗ i n i t i a l i z e r s f o r row i n d e x e d by 1 ∗/ /∗ i n i t i a l i z e r s f o r row i n d e x e d by 2 ∗/ En realidad no es necesario escribirlo de esta forma, también es posible inicializarla de la siguiente forma: int a [ 3 ] [ 4 ] = { 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 1 0 , 1 1 } ; En C es posible declarar un arreglo de más de dos dimensiones, por ejemplo de tres dimensiones, ver Figura 7 esto se debe declarar de la siguiente forma: 4.2 Vectores, Punteros y Pasaje de Vectores como parámetros En el lenguaje de Programación C existe una muy estrecha relación entre los vectores y los punteros [2,1]. A continuación se muestra la relación entre los vectores y los punteros en C: int v e c t o r [ 1 0 ] = ” 1 2 , 2 3 , 3 4 , 4 5 , 5 6 , 6 7 , 7 8 , 8 9 , 9 0 , 100 ” ; int ∗ p t r E n t e r o ; int unValorEntero ; Las siguiente expresiones son equivalentes: ptrEntero= &vetor[0] ip=vector unValorEntero=*ptrEntero unValorEntero=*ptrEntero *(ptrEntero+1) v[1] ptrEntero+i &vector[i] Algoritmos y Programacón I - 75.40 - Cat. Garcia 7 0,1 7 ,0 ,0 1,0 ,0 9 0,2 ,0 1,1 ,0 2,0 ,0 8 4 0,0 9 3 6 1 5 2 10 1 1,2 ,0 2,1 ,0 5 3 6 4 2,2 2 ,0 8 Fig. 7. Una matriz de tres dimensiones 4.3 Pasaje de Vectores por Parámetros En primer lugar, cuando se necesita definir un parámetro formal como un vector, se lo define de la siguiente forma: int SumarElementosDeVector ( int unVector [ ] ) { } No es necesario poner la longitud del vector que se espera como parámetro. Como se ha visto en las igualdades anteriores la llamada a la función sumar puede ser escrita como : int suma=SumarElementosDeVector(& v e t o r [ 0 ] ) ; int suma=SumarElementosDeVector ( v e t o r ) ; esta última es la más utilizada. Como se puede apreciar los vectores o arreglos (cualquiera sea su dimensión) SIEMPRE se pasan por referencia. 5 Un Ejemplo Completo del uso de Vectores Dados dos arreglos cuyos elementos contienen valores enteros, realizar un programa en C que solucione los siguientes apartados: 1. 2. 3. 4. 5. Cargue ambos vectores con valores ingresados por el usuario Calcule el vector suma Calcule el vector resta Calcule el producto escala entre ambos vectores Calcule el módulo Introducción a los Arreglos y Punteros 11 #include<s t d i o . h> #include<math . h> #define LONGITUD 10 void sumar ( int vectorOperandoUno [ ] , int vectorOperandoDos [ ] , int vectorSuma [ ] void r e s t a r ( int vectorOperandoUno [ ] , int vectorOperandoDos [ ] , int v e c t o r R e s t a long p r o d u c t o E s c a l a r ( int vectorOperandoUno [ ] , int vectorOperandoDos [ ] ) ; void l e e r V e c t o r ( int unVector [ ] ) ; double modulo ( int vectorOperandoUno [ ] ) ; void m o s t r a r V e c t o r ( int unVector [ ] ) ; int main ( ) { int unVector [LONGITUD ] ; int o t r o V e c t o r [LONGITUD ] ; int r e s u l t a d o [LONGITUD] = { 0 } ; p r i n t f ( ” I n g r e s a r l o s d a t o s d e l p r i m e r v e c t o r \n” ) ; l e e r V e c t o r ( unVector ) ; p r i n t f ( ” I n g r e s a r l o s d a t o s d e l segundo v e c t o r \n” ) ; leerVector ( otroVector ) ; sumar ( unVector , o t r o V e c t o r , r e s u l t a d o ) ; mostrarVector ( r e s u l t a d o ) ; r e s t a r ( unVector , o t r o V e c t o r , r e s u l t a d o ) ; mostrarVector ( r e s u l t a d o ) ; p r i n t f ( ” e l p r o d u c t o e s c a l a r de l o s dos V e c t o r e s e s : %l d \n” , p r o d u c t o E s c a p r i n t f ( ” e l modulo d e l p r i m e r v e c t o r e s : %f \n” , modulo ( unVector ) ) ; p r i n t f ( ” e l modulo d e l segundo v e c t o r e s : %f \n” , modulo ( o t r o V e c t o r ) ) ; } void sumar ( int vectorOperandoUno [ ] , int vectorOperandoDos [ ] , int vectorSuma [ int i ; f o r ( i =0; i <LONGITUD; i ++) vectorSuma [ i ]= vectorOperandoUno [ i ]+ vectorOperandoDos [ i ] ; } void r e s t a r ( int vectorOperandoUno [ ] , int vectorOperandoDos [ ] , int vectorSuma int i ; f o r ( i =0; i <LONGITUD; i ++) vectorSuma [ i ]= vectorOperandoUno [ i ]− vectorOperandoDos [ i ] ; } 12 Algoritmos y Programacón I - 75.40 - Cat. Garcia long p r o d u c t o E s c a l a r ( int vectorOperandoUno [ ] , int vectorOperandoDos [ ] ) { int i ; long s u m a t o r i a =0; f o r ( i =0; i <LONGITUD; i ++) s u m a t o r i a+=vectorOperandoUno [ i ] ∗ vectorOperandoDos [ i ] ; return s u m a t o r i a ; } void l e e r V e c t o r ( int unVector [ ] ) { int i ; f o r ( i =0; i <LONGITUD; i ++){ p r i n t f ( ” Vector [%d ] = ” , i ) ; s c a n f ( ”%d” ,& unVector [ i ] ) ; } } double modulo ( int OperandoUno [ ] ) { int i ; double suma=0; f o r ( i =0; i <LONGITUD; i ++){ suma+=OperandoUno [ i ] ∗ OperandoUno [ i ] ; } return s q r t ( suma ) ; } void m o s t r a r V e c t o r ( int unVector [ ] ) { int i ; f o r ( i =0; i <LONGITUD; i ++) p r i n t f ( ”%d” , unVector [ i ] ) ; } este ejemplo puede ser descargado, compilado y ejecutado desde https:// www.dropbox.com/s/2e28zc64wbyf580/ejemplo.c?dl=0 6 Simulación de Vectores de Longitud Variable En C como en muchos otros lenguajes de programación no es posible declarar vectores que puedan variar la cantidad de elementos que almacenan. Por ello se dice que los vectores son tipos de datos estáticos, pues no se puede alterar su tamaño (en bytes) en tiempo de ejecución del programa. Introducción a los Arreglos y Punteros 13 De todas formas es muy común que sea necesario, dadas las caracterı́sticas del problema que se necesite, variar la cantidad de elementos que contiene un vector en tiempos de ejecución ... Entonces, ¿Cómo lo hacemos si el lenguaje no lo permite? La respuesta es sencilla, se define un vector de una longitud conocida, a priori, que dentro del dominio del problema nunca podrá ser superada. En otras palabras, se define un vector muy grande. Y además, se utiliza una variable para almacenar la información del tamaño o tope utilizados del vector, ver Figura 8. Tope del Vector Vector Fig. 8. Uso acotado del tamaño de un vector El par vector tope siempre van juntos durante la ejecución del programa. Teniendo en cuenta ahora esta forma de simular vectores de longitud variable o de tamaño variable, podemos modificar el ejemplo anterior para que el usuario seleccione la longitud de los dos vectores: Dados dos arreglos cuyos elementos contienen valores enteros, y cuya dimensión se ingresa por teclado, realizar un programa en C que solucione los siguientes apartados: 1. 2. 3. 4. 5. Cargue ambos vectores con valores ingresados por el usuario Calcule el vector suma Calcule el vector resta Calcule el producto escala entre ambos vectores Calcule el modulo #include<s t d i o . h> #include<math . h> #define LONGITUD 10 void sumar ( int vectorOperandoUno [ ] , int vectorOperandoDos [ ] , int vectorSuma [ ] void r e s t a r ( int vectorOperandoUno [ ] , int vectorOperandoDos [ ] , int v e c t o r R e s t a 14 Algoritmos y Programacón I - 75.40 - Cat. Garcia long p r o d u c t o E s c a l a r ( int vectorOperandoUno [ ] , int vectorOperandoDos [ ] , int t o void l e e r T o p e ( int ∗ t o p e ) ; void l e e r V e c t o r ( int unVector [ ] , int t o p e ) ; double modulo ( int vectorOperandoUno [ ] , int t o p e ) ; void m o s t r a r V e c t o r ( int unVector [ ] , int t o p e ) ; int main ( ) { int unVector [LONGITUD ] ; int t o p e =0; int o t r o V e c t o r [LONGITUD ] ; int r e s u l t a d o [LONGITUD] = { 0 } ; l e e r T o p e (& t o p e ) ; printf (” Ingresar los l e e r V e c t o r ( unVector , printf (” Ingresar los leerVector ( otroVector d a t o s d e l p r i m e r v e c t o r \n” ) ; tope ) ; d a t o s d e l segundo v e c t o r \n” ) ; , tope ) ; sumar ( unVector , o t r o V e c t o r , r e s u l t a d o , t o p e ) ; mostrarVector ( resultado , tope ) ; r e s t a r ( unVector , o t r o V e c t o r , r e s u l t a d o , t o p e ) ; mostrarVector ( resultado , tope ) ; p r i n t f ( ” e l p r o d u c t o e s c a l a r de l o s dos V e c t o r e s e s : %l d \n” , p r o d u c t o E s c a p r i n t f ( ” e l modulo d e l p r i m e r v e c t o r e s : %f \n” , modulo ( unVector , t o p e ) ) ; p r i n t f ( ” e l modulo d e l segundo v e c t o r e s : %f \n” , modulo ( o t r o V e c t o r , t o p e ) } void sumar ( int vectorOperandoUno [ ] , int vectorOperandoDos [ ] , int vectorSuma [ int i ; f o r ( i =0; i <t o p e ; i ++) vectorSuma [ i ]= vectorOperandoUno [ i ]+ vectorOperandoDos [ i ] ; } void r e s t a r ( int vectorOperandoUno [ ] , int vectorOperandoDos [ ] , int vectorSuma int i ; f o r ( i =0; i <t o p e ; i ++) vectorSuma [ i ]= vectorOperandoUno [ i ]− vectorOperandoDos [ i ] ; } long p r o d u c t o E s c a l a r ( int vectorOperandoUno [ ] , int vectorOperandoDos [ ] , int t o int i ; long s u m a t o r i a =0; f o r ( i =0; i <t o p e ; i ++) Introducción a los Arreglos y Punteros 15 s u m a t o r i a+=vectorOperandoUno [ i ] ∗ vectorOperandoDos [ i ] ; return s u m a t o r i a ; } void l e e r T o p e ( int ∗ t o p e ) { p r i n t f ( ” I n g r e s e l a d i m e n s i o n de l o s v e c t o r e s \n” ) ; s c a n f ( ”%d” , t o p e ) ; } void l e e r V e c t o r ( int unVector [ ] , int t o p e ) { int i ; f o r ( i =0; i <t o p e ; i ++){ p r i n t f ( ” Vector [%d ] = ” , i ) ; s c a n f ( ”%d” ,& unVector [ i ] ) ; } } double modulo ( int OperandoUno [ ] , int t o p e ) { int i ; double suma=0; f o r ( i =0; i <t o p e ; i ++){ suma+=OperandoUno [ i ] ∗ OperandoUno [ i ] ; } return s q r t ( suma ) ; } void m o s t r a r V e c t o r ( int unVector [ ] , int t o p e ) { int i ; f o r ( i =0; i <t o p e ; i ++) p r i n t f ( ”%d” , unVector [ i ] ) ; } El mismo concepto es aplicable para las matrices y los arreglos multidimensionales, por cada dimensión es necesario almacenar el tope. El ejemplo puede ser descrgado, compilado y ejecutado desde : aquı́ 7 Registros Un registro o struct en C es un tipo de dato estructurado, que define a una lista de variables agrupadas fı́sicamente bajo un mismo nombre en un bloque de memoria, permitiendo de esta forma que estas sean accedidas mediante la utilización de un único nombre (que como ya sabemos en C equivale a la variable puntero que referencia a dicha estructura). 16 Algoritmos y Programacón I - 75.40 - Cat. Garcia Un struct o registro puede contener ya sea a otros tipos de datos estructurados como a tipos de datos simples. Se debe tener en cuenta que los struct o registros permiten, al contrario de los vectores, agrupar variables de tipos de datos disı́miles que guardan alguna relación entre sı́. struct unNombre { t i p o campo1 ; t i p o campo2 ; t i p o campo3 ; t i p o campo4 ; }; También es posible utilizar y declarar estructuras utilizando la palabra reservada de C typdef. Su función es asignar un nombre alternativo a tipos existentes, a menudo cuando su declaración normal es aparatosa o potencialmente confusa, por ejemplo: typedef struct f e c h a { unsigned short d i a ; unsigned short mes ; unsigned int a n i o ; } Tfecha ; typedef char [ 9 ] Tdocumento ; struct p e r s o n a { char nombre [ 4 0 ] ; char a p e l l i d o [ 4 0 ] Tdocumento documento Tfecha fechaDeNacimiento ; } Tpersona ; Tpersona unaPersona ; Cada una de las variables que componen a un struct o registro se denomina campo o miembro. Al igual que los arreglos estas variables pueden ser inicializadas: /∗ D e c l a r a c i ó n a n t i c i p a d a d e l t i p o de d a t o ” punto ” . ∗/ typedef struct punto Tpunto ; /∗ D e c l a r a c i o n d e l s t r u c t o r e g i s t r o con l o s campos o miemobros x , y ∗/ struct punto { int x; int y; }; Introducción a los Arreglos y Punteros 17 Inicialización al estilo C-89, solo puede ser hecha cuando los valores de los campos son ingresados en orden y en forma contigua: /∗ d e f i n e una v a r i a b l e de t i p o Tpunto e i n i c i a l i z a s u s miembros en e l mismo l u point p = {1 ,2}; Si la inicialización no es en orden, entonces: /∗ D e f i n e una v a r i a b l e de t i p o Tpunto e i n i c i a l i z a s u s miembros ∗/ point p = {. y = 2 , . x = 1}; 7.1 Registros: Asignación Como se puede suponer la asignación de una variable de tipo struct a otra puede hacerse en un único paso, con lo cual se asigna una variable a otra. O puede hacerse miembro a miembro: #include<s t d i o . h> /∗ D e c l a r a c i o n d e l s t r u c t o r e g i s t r o con l o s campos o miemobros x , y ∗/ struct punto { int x; int y; } Tpunto ; int main ( ) { Tpunto unPunto ={1 ,2}; Tpunto otroPunto ; Tpunto otroPuntoMas ; /∗ s e a s i g n a l o s v a l o r e s de t o d o s l o s miembros de una v a r i a b l e a o t r a ∗/ otroPunto = unPunto ; /∗ s e c o p i a campo a campo l o s v a l o r e s de una v a r i a b l e a o t r a ∗/ otroPuntoMas . x=unPunto . x ; otroPuntoMas . y=unPunto . y ; otroPunto . x+=1; i f ( otroPunto . x != otroPuntoMas . x ) return 0 ; } p r i n t f ( ” El campo x:%d e l Campo y :%d 18 7.2 Algoritmos y Programacón I - 75.40 - Cat. Garcia Registros: Punteros Al igual que en cualquier otro tipo de dato , en C uno puede definir un puntero a un struct, se verá la operatoria en el ejemplo: struct punto { int x ; int y ; }; struct punto MiPunto = { 1 , 3 } ; struct punto ∗ ptrPunto = &miPunto ; ( ∗ ptrPunto ) . x = 8 ; ptrPunto−>x = 8 ; /∗ a c c e d e r a l primer miembro d e l r e g i s t r o ∗/ /∗ o t r a forma de h a c e r l o mismo ∗/ References 1. Harvey M Deitel, Paul J Deitel, and TR Nieto. C++ how to program, volume 4. Prentice Hall Englewood cliffs, 1994. 2. B. W. Kernighan and D. M. Ritchie. The C Programming Language. Prentice-Hall, Englewood Cliffs, New Jersey, 1978.