Capítulo 8 - Apuntadores.pdf

Embed Size (px)

Citation preview

  • 7/25/2019 Captulo 8 - Apuntadores.pdf

    1/36

    ITSON Manuel Domitsu Kono

    Captulo 8

    Apuntadores

    Direcciones de Memoria

    Podemos imaginarnos la memoria principal de una computadora como un conjunto deceldas consecutivas de memoria cada una de un tamao de un byte. Cada celda tiene su

    propia direccin, como se ilustra en la figura 8-1.

    Figura 8-1. Memoria Principal

    Una variable aparte de tener un nombre tiene tambin una direccin. Esta direccin esnica. Si la variable es de un byte su direccin es la direccin de la celda que la contiene.Si una variable ocupa dos o ms bytes, su direccin es la direccin de su primera celda,esto es la direccin ms baja. En la figura 8-2 se muestra el mismo bloque de memoria de

    la figura 8-1 despus de que se han hecho las siguientes declaraciones, suponiendo queuna variable de tipo int ocupa 4 bytes de memoria:

    char x = 8;i nt y = 1234;

  • 7/25/2019 Captulo 8 - Apuntadores.pdf

    2/36

    124 Apuntadores

    ITSON Manuel Domitsu Kono

    Figura 8-2. Memoria principal con variables

    Dado que cada variable tiene una direccin nica, es posible referirse a una variable ya

    sea por su nombre o por su direccin. Por ejemplo podramos referirnos a la variable xdeclarada anteriormente, como a la variable de tipo char que tiene la direccin 1000 y a ycomo a la variable entera cuya direccin es 1001. De hecho, en el lenguaje mquina todaslas referencias a las variables son a travs de sus direcciones ya que no existen losnombres de variables. Uno de los grandes avances introducidos por los lenguajes deprogramacin es el concepto de los nombres simblicos de las variables tal como x, y. Loque nos libera de recordar las direcciones en las que se encuentran las variables.

    Una de las caractersticas con las que fue diseado el lenguaje C es la permitirnos uncontrol casi completo del hardware al mismo tiempo de que la programacin fuese al

    mismo nivel que con un lenguaje de alto nivel. Para lograr este control del hardware, ascomo para hacer ms eficientes algunas de las tareas para acceder las variables, Crequiere de la capacidad de manipular directamente las direcciones de memoria.

    Operador de Direccin (&)

    En realidad, desde los primeros programas hemos usado el concepto de direccin de unavariable. Recuerde que en la funcin scanf ( ) , le pasamos como argumentos lasdirecciones de las variables donde queremos que se almacenen los datos ledos. Paradeterminar la direccin en que se encuentra una variable usamos el operador dedireccin (&), el cual es un operador unario que nos da la direccin de una variable. El

    operador & slo opera con variables creadas en la memoria no con expresiones nivariables registro. Para las declaraciones de variables del ejemplo anterior, la expresin&x vale 1000 y &y vale 1001. El operador de direccin aparece en la tabla deprecedencias en la segunda lnea.

  • 7/25/2019 Captulo 8 - Apuntadores.pdf

    3/36

    Captulo 8 Apuntadores 125

    ITSON Manuel Domitsu Kono

    Apuntadores

    Las direcciones de las variables son constantes, esto es, no cambian de posicin durantela ejecucin del programa. Sin embargo la necesidad de crear expresiones para calcular

    de direccin de un dato o de escribir instrucciones que operen con diferentes direccionesintroduce la necesidad de tener variables que en lugar de almacenar datos comunes,almacenen direcciones. A tales variables se le conocen como apuntadores.

    Al igual que con las variables comunes los apuntadores deben declararse antes deusarse. La sintaxis para declarar un apuntador es la siguiente:

    tipo *nomPvar1[ =pExp1] [ , *nomPvar2[ =pExp2] . . . ]

    nomPvar1, nomPvar2 ... son los apuntadores que se estn declarando. El asterisco al

    lado de cada identificador indica que es una declaracin de un apuntador y no de una

    variable comn. El apuntador va a contener una direccin de un dato del tipo tipoespecificado en la declaracin. Se dice que el apuntador apunta al dato del tipoespecificado.

    Al igual que con las variables comunes, los apuntadores pueden inicializarse al momentode su declaracin.pExp1,pExp2, ... son expresiones que al evaluarse nos dan las

    direcciones a las que se inicializan los apuntadores nomPvar1, nomPvar2 ...,

    respectivamente.

    Por ejemplo:

    char *px;i nt *py;

    Aqu estamos declarando a pxcomo un apuntador a carcter y a pycomo un apuntador aentero. Esto es, pxva a contener la direccin de una variable de tipo carcter y pyla deuna variable de tipo entero.

    Antes de poder usar un apuntador, ste debe apuntar a una variable, esto es, debemosasignarle la direccin de una variable. Esto se puede hacer inicializando el apuntador aldeclararlo o mediante una asignacin posterior. Por ejemplo.

    char x = 8;

    i nt y = 1234;char *px = &x;i nt *py;

    . . .py = &y;

    Despus de efectuarse las asignaciones anteriores, pxapunta a x, esto es, contiene ladireccin de xy pyapunta a y. Esto se ilustra en la figura 8-3.

  • 7/25/2019 Captulo 8 - Apuntadores.pdf

    4/36

    126 Apuntadores

    ITSON Manuel Domitsu Kono

    Figura 8-3.

    Inicializacin de apuntadores por ausencia

    Los conceptos de clase de almacenamiento y alcance lxico se aplican de igual forma alos apuntadores que a las variables normales. Los apuntadores con clase dealmacenamiento automtica si no son inicializados tienen una direccin indefinida llamadadireccin basura. Si son inicializados, el inicializador puede ser cualquier expresin quepueda ser evaluada al tiempo de la inicializacin y que produzca una direccin vlida. Lainicializacin se hace cada vez que se entra a la funcin o bloque.

    Si los apuntadores son de clase de almacenamiento esttica y no son inicializados, el

    compilador los inicializa a una direccin especial llamada direccin nula. En el caso deser inicializadas explcitamente, los apuntadores con clase de almacenamiento estticadeclarados fuera de las funciones (externos) deben inicializarse a una direccin constante,o la direccin de una variable externa. Los apuntadores con clase de almacenamientoesttica declarados en un bloque (estticos) deben inicializarse a una direccin constante,o la direccin de una variable externa o esttica en la misma funcin. La inicializacin serealiza una vez, antes de que el programa inicialice su ejecucin.

    Direccin Basura

    Una direccin basuraes una direccin al azar. Un apuntador con una direccin basura

    puede apuntar a una de estas tres direcciones: La direccin de una variable del programa,la direccin donde est una instruccin del programa o a una direccin que no lepertenece al programa. En el primer caso corromperamos el contenido de una variable,en el segundo caso estaramos modificando una instruccin del programa y en el tercercaso, dependiendo de la proteccin de memoria que ofrezca el sistema operativo,pudiramos corromper los datos o cdigo de otro programa o inclusive del sistemaoperativo. Como resultado puede suceder que el programa se comporte en forma errneao deje de funcionar.

  • 7/25/2019 Captulo 8 - Apuntadores.pdf

    5/36

    Captulo 8 Apuntadores 127

    ITSON Manuel Domitsu Kono

    Direccin Nula

    Una direccin nula representa una direccin especial que la definicin del lenguaje C,asegura que no pertenece a ningn objeto o funcin a la que pueda hacer referencia elprograma. Como esta direccin no le pertenece a ningn programa, si escribimos en esta

    direccin no corromperemos a ningn dato o instruccin. Si no vamos a inicializar a unapuntador al momento de declararlo, sino hasta ms adelante en el cdigo, es una buenaprctica de programacin inicializarlo a esa direccin nula para evitar queinadvertidamente usemos el apuntador y escribamos en cualquier direccin.

    Apuntador Nulo

    En los datos numricos, el cero denota la ausencia de lo que representa el dato. De lamisma manera, en el lenguaje C, un apuntador nulo representa una direccin que noexiste, es decir, la definicin del lenguaje C asegura que un apuntador nulo es unadireccin "especial" diferente a la direccin de cualquier objeto o funcin a la que puedahacer referencia el programa. Si inicializamos un apuntador a un apuntador nulo queremosdecir que ese apuntador no apunta a lado alguno.

    Hay que hacer la distincin entre un apuntador nulo y un apuntador no inicializado. Unapuntador nulo no apunta a algn lado mientras que un apuntador no inicializado puedeapuntar a cualquier lado.

    Un apuntador nulo se representa por la constante cero (0). Cuando el compilador ve laconstante cero en el contexto de un apuntador la convierte a un apuntador nulo. Porejemplo en la siguiente declaracin pxse est inicializando a un apuntador nulo:

    i nt px = 0;

    mientras que en la siguiente expresin estamos comparando el valor de px con unapuntador nulo

    px == 0

    Sin embargo si uno de los argumentos de una llamada a una funcin es un apuntador y noexiste el prototipo de la funcin, el compilador puede fallar en interpretar el cero comoapuntador nulo. En estos casos se debe aplicar el operador cast para convertir el 0 a unapuntador nulo del tipo esperado por la funcin. Por ejemplo supongamos que la funcin

    f 1() tiene un apuntador a char como parmetro, y deseamos llamar a la funcinpasndole un apuntador nulo, la llamada a la funcin debe escribirse como

    f 1( ( char *) 0 )

    Si existe el prototipo de la funcin, el compilador podr realizar la conversincorrectamente y no ser necesario el operador cast.

  • 7/25/2019 Captulo 8 - Apuntadores.pdf

    6/36

    128 Apuntadores

    ITSON Manuel Domitsu Kono

    El lenguaje C define la macro

    #def i ne NULL 0

    en los archivos de encabezados stdio.h y stddef.h. Podemos usar 0 o NULLindistintamente en el contexto de apuntadores. No debemos usar NULLpara indicar unaconstante numrica que valga cero.

    Operador de indireccin

    Suponga que se han hecho las siguientes declaraciones:

    i nt x = 8, *px = &x;

    y que posteriormente deseamos acceder el contenido de la variable xpara cambiarlo a 5.Una de las formas es a travs de su nombre

    x = 5

    La segunda forma es utilizar el apuntador a esa variable, que es px

    *px = 5

    en la expresin anterior, el asterisco se conoce como el operador de indireccino dedesreferenciacin . Este operador unario nos permite acceder a la variable cuya direccinest dada por su operando. El operando del operador de indireccin es una expresin queproduce una direccin. En este ejemplo, modificamos el valor de la variable xindirectamente a travs de la variable px. Este concepto se conoce comodireccionamiento indirecto o simplemente como indireccin. La precedencia yasociatividad del operador de indireccin son las mismas que las del operador dedireccin.

    La expresin *px del ejemplo anterior es equivalente a x, esto es, dado que x puedeaparecer en cualquier expresin donde aparezca un entero, *pxtambin lo puede hacer.Por ejemplo

    x += 5;

    se puede escribir como

    *px += 5;

    Sin embargo, la expresin

    x++

    debe escribirse como

  • 7/25/2019 Captulo 8 - Apuntadores.pdf

    7/36

    Captulo 8 Apuntadores 129

    ITSON Manuel Domitsu Kono

    ( *px)++

    Los parntesis son importantes pues lo que queremos es incrementar el valor apuntadopor px. Si omitimos los parntesis

    *px++dada la asociatividad de los operadores (ya que tienen la misma precedencia), equivale a

    *( px++)

    y lo que estaramos aumentando es el valor de pxy no el valor al que apunta.

    Un aspecto importante es el hecho de que un apuntador apunta a una variable de un tipodado. Ya vimos que en la declaracin

    char x = 8, *px = &x;i nt y = 1234, *py;

    la asignacin px = &xes correcta. Sin embargo la asignacin

    px = &y

    genera un error del compilador, pues px es una variable que apunta a una variablecarcter y no a una variable entero.

    Apuntadores y el calificador const

    En el Captulo 3: Tipos de Datos y Expresiones en C vimos que el calificador constpuedeaplicarse a la declaracin de cualquier variable para especificar que su valor no cambia,comportndose como una constante. Por consiguiente, no podemos obtener la direccinde esa variable ya que de hacerlo pudiramos asignrselo a un apuntador y usar stepara acceder indirectamente a la variable y modificarla. Por ejemplo

    const i nt x = 8;i nt *px = &x; / / Er r or de compi l aci n

    As como podemos calificar a una variable como const , podemos hacer lo mismo con unapuntador. Por ejemplo

    i nt x = 5, y = 6;i nt *const px = &x;

    En esta segunda declaracin decimos que pxno puede cambiar su valor. Sin embargo elvalor apuntado por pxsi puede cambiar

    *px = 7; / / Val i da

  • 7/25/2019 Captulo 8 - Apuntadores.pdf

    8/36

    130 Apuntadores

    ITSON Manuel Domitsu Kono

    px = &y; / / Er r or de compi l aci n

    Tambin podemos permitir que el apuntador cambie de valor pero la variable apuntada porel apuntador no. Por ejemplo

    i nt x = 5, y = 6;

    const i nt *px = &x;

    En esta segunda declaracin decimos que px puede cambiar su valor. Sin embargo elvalor apuntado por pxno puede cambiar

    px = &y; / / Val i da*px = 7; / / Er r or de compi l aci n

    Por ltimo podemos impedir que tanto el apuntador y la variable a la que apunte cambiende valor. Por ejemplo

    i nt x = 5, y = 6;

    const i nt const *px = &x;

    En esta segunda declaracin decimos que ni px ni el valor apuntado por px puedencambiar.

    *px = 7; / / Er r or de compi l aci npx = &y; / / Er r or de compi l aci n

    Apuntadores como Parmetros deFunciones

    Una de las limitantes que tienen las funciones en C, es de que slo pueden regresar unvalor por el mecanismo de return. Cuando deseamos que una funcin "regrese" ms deun valor podemos recurrir al uso de variables externas tal como se plante en el ejemplo 1del Captulo 6: Funciones. Sin embargo esta solucin va en contra de la idea de que lacomunicacin entre funciones debe ser a travs de parmetros y del mecanismo de returnya que una variable externa es conocida por todo el programa y debemos tener mscuidado para no alterarla inadvertidamente.

    Una segunda alternativa para resolver este problema es que la funcin llamante declarelas variables que requiere para recibir los datos y le pase a la funcin llamada lasdirecciones de las variables. Con esto le permite el acceso a las variables. La funcinllamada puede modificar directamente las variables en la funcin llamante simulando asque le regresan valores. El mecanismo anterior se ilustra en la figura 8-4.

    Podemos ver que la funcin f0( ) declara dos variables xe y. Al llamar a la funcin f1( ) la funcin f0( ) le pasa las direcciones de las variables, &xy &y.

  • 7/25/2019 Captulo 8 - Apuntadores.pdf

    9/36

    Captulo 8 Apuntadores 131

    ITSON Manuel Domitsu Kono

    Figura 8-4

    voi d f 0( voi d) {i nt x, y;. . .f 1( &x, &y) ;. . .

    }

    La funcin f1( ) recibe estas direcciones en sus parmetros tipo apuntador, px y py,obteniendo as el acceso a las variables xe yde f0( ) .

    voi d f 1( i nt *px, i nt *py) {. . .

    }

    El uso de apuntadores como parmetros de una funcin no slo nos permite que lafuncin "regrese" ms de un valor. Dado a que la funcin tiene acceso a las variablescuyas direcciones constituyen sus parmetros, la funcin puede tomar los valores que ah

    se encuentran. Esto es, los parmetros apuntadores permiten que la funcin no slo"regrese" valores sino que tambin los "reciba".

    El mecanismo explicado anteriormente, para simular que una funcin nos regresa ms deun valor se usa ampliamente en C. De hecho una funcin que hemos usado desdenuestro primer programa lo emplea, la funcin scanf ( ) . Recuerde que la funcinscanf ( ) requiere que le pasemos las direcciones de las variables en las que va aalmacenar los datos ledos. Al darle las direcciones de las variables le damos el acceso adichas variables.

    Dado que es vlido cambiar el contenido de un parmetro de una funcin, en el ejemploanterior podramos inadvertidamente modificar el valor de los parmetros apuntadores,esto traera como consecuencia que estos ya no apuntaran a las variables a las que sedesea "regresar" los valores. Para evitar esa posibilidad podemos declarar los parmetrosde la siguiente forma:

    voi d f 1( i nt *const px, i nt *const py) {. . .

    }

  • 7/25/2019 Captulo 8 - Apuntadores.pdf

    10/36

    132 Apuntadores

    ITSON Manuel Domitsu Kono

    As cualquier intento por modificar los valores de px o py generaran un error delcompilador.

    Ejemplo sobre Apuntadores como Parmetros de Funciones

    Modifique el programa para el clculo del rea bajo una curva del ejemplo 1 del Captulo 6:Funciones, para hacer que la funcin usada para leer los datos en lugar de usar variablesglobales para las abcisas, las "regrese" por el mecanismo de parmetros apuntador.

    Recordemos que la funcin l eeDat os( ) lee del teclado la abscisa inicial, xi , la abscisafinal, xf y el nmero de rectngulos, n. La funcin l eeDat os( ) regresa por elmecanismo de return el nmero de rectngulos, y recibir como parmetros lasdirecciones de las variables xi y xfque se encuentran en la funcin main() y que guardanlos valores de xi y xf. La declaracin de la funcin l eeDat os( ) tiene la forma:

    i nt l eeDat os( f l oat *const pxi , f l oat *const pxf ) ;

    La funcin cal cul aAr ea( ) regresa el valor del rea bajo la curva, un flotante. Estafuncin requiere para poder calcular el rea de los valores de las abscisas inicial y final ydel nmero de rectngulos. Estos valores los debe recibir de la funcin mai n( ) , ya que esquien la llama. La declaracin de cal cul aAr ea( ) queda como:

    f l oat cal cul aArea( f l oat xi , f l oat xf , i nt n) ;

    La funcin escr i beAr ea( ) no se modifica ni en su declaracin, ni en su definicin, ni ensu llamada.

    La definicin de la funcin l eeDat os( ) queda como:

    i nt l eeDat os( f l oat *const pxi , f l oat *const pxf ) {i nt n;

    pr i nt f ( "\ nEst e pr ograma t abul a el ar ea baj o l a cur va y = x 2, ") ;printf("\nentre las abscisas x = xi y x = xf. Utiliza el metodo");printf("\ndel r ectangul o\ n") ;

    pr i ntf (" \ nAbsci sa i ni ci al : " ) ;scanf ( "%f ", pxi ) ;

    pr i nt f (" \ nAbsci sa f i nal : " ) ;scanf ( "%f ", pxf ) ;

    pr i nt f ( "\ nNumer o de r ect angul os: ") ;scanf ( "%d", &n) ;

    r et ur n n;}

    Recuerde que los parmetros pxi y pxfson apuntadores y la funcin scanf ( ) requiereque le pasemos las direcciones de las variables en que va a dejar los datos. Como esas

  • 7/25/2019 Captulo 8 - Apuntadores.pdf

    11/36

    Captulo 8 Apuntadores 133

    ITSON Manuel Domitsu Kono

    direcciones estn en pxi y pxf, las llamadas a scanf ( ) utiliza directamente a pxi y apxfcomo argumentos. La funcin cal cul aAr ea( ) tiene la siguiente definicin:

    f l oat cal cul aArea( f l oat xi , f l oat xf , i nt n) {f l oat base, sumaH, x, y, ar ea;

    sumaH = 0;base = (xf - xi ) / n;

    f or ( x = xi ; x < xf ; x += base) {y = x * x;sumaH += y;

    }

    area = base * sumaH;r et ur n ar ea;

    }

    Aqu la nica diferencia es el que los valores de xi y xfle llegan a la funcin mediante losparmetros en lugar de tomarlos de las variables externas.

    La llamada a las funcin l eeDat os( ) es:

    nRect = l eeDat os( &xi , &xf ) ;

    donde nRect es una variable entera en la que se almacena el nmero de rectngulos.Recuerde que al llamar a la funcin hay que pasarle las direcciones de las variables xi ,xf. La llamada a la funcin cal cul aAr ea( ) es:

    ar ea = cal cul aArea( xi , xf , nRect) ;

    Le estamos enviando los tres datos por parmetros. El programa completo se muestra acontinuacin:

    / ** Fi l e: area5. c* Aut hor : mdomi t su** Created on 4 de enero de 2010, 12: 09 PM

    */

    #i ncl ude #i ncl ude / ** Est e pr ogr ama tabul a el area baj o l a cur va y = x 2, ent r e l as* absci sas x = xi y x = xf . Ut i l i za el mt odo del r ectangul o.*/

    / / Decl ar aci n de f unci onesi nt l eeDat os( f l oat *const pxi , f l oat *const pxf ) ;f l oat cal cul aArea( f l oat xi , f l oat xf , i nt n) ;voi d escri beArea( f l oat area) ;

    i nt mai n( voi d) {i nt nRect ;f l oat x i , xf , area;

  • 7/25/2019 Captulo 8 - Apuntadores.pdf

    12/36

    134 Apuntadores

    ITSON Manuel Domitsu Kono

    / / Lee xi , xf y nnRect = l eeDat os( &xi , &xf ) ;

    / / Cal cul a el ar eaar ea = cal cul aAr ea( xi , xf , nRect) ;

    / / Escri be ar eaescr i beAr ea( ar ea) ;

    r etur n ( EXI T_SUCCESS) ;}

    / / Def i ni ci n de f unci ones

    / ** Esta f unci n l ee del t ecl ado l os val or es de l a absci sa i ni ci al , xi ,* absci sa f i nal , xf , y el nmer o de rect ngul os.** Regresa el nmero de rectngul os y guar da en l as vari abl es apunt adas por* l os apunt ador es pxi y pxf l os val ores de xi y xf .*/

    i nt l eeDat os( f l oat *const pxi , f l oat *const pxf ) {i nt n;

    pr i nt f ( "\ nEst e pr ogr ama t abul a el ar ea baj o l a cur va y = x 2, ent r e l as") ;pr i nt f ( "\ nabsci sas x = xi y x = xf . Ut i l i za el met odo del rect angul o\ n") ;

    / / Lee l a absci sa i ni ci alpr i ntf (" \ nAbsci sa i ni ci al : " ) ;scanf ( "%f ", pxi ) ;

    / / Lee l a absci sa f i nalpr i ntf (" \ nAbsci sa f i nal : " ) ;scanf ( "%f ", pxf ) ;

    / / Lee el nmero de r ectngul ospr i nt f ( "\ nNumer o de r ect angul os: ") ;scanf ( "%d", &n) ;

    ret ur n n;}

    / ** Esta f unci on cal cul a el ar ea baj o l a cur va y = x 2 ent r e l as absci sas* xi y xf , usando el metodo del paral el ogr amo con n r ect ngul os. La f unci n* r eci be l os val ores de xi y xf y el nmer o de r ect angul os.* La f unci n r egr esa el ar ea.*/

    f l oat cal cul aArea( f l oat xi , f l oat xf , i nt n) {f l oat base, sumaH, x, y, ar ea;

    sumaH = 0;

    / / Cal cul a basebase = (xf - xi ) / n;

    / / Par a cada r ect ngul of or ( x = xi ; x < xf ; x += base) {

    / / Cal cul amos l a al t ura del r ect ngul oy = x * x;

    / / Acumul amos al t urasumaH += y;

    }

  • 7/25/2019 Captulo 8 - Apuntadores.pdf

    13/36

    Captulo 8 Apuntadores 135

    ITSON Manuel Domitsu Kono

    / / Cal cul a el ar eaarea = base * sumaH;

    ret ur n ar ea;}

    / ** Est a f unci n despl i ega en l a pant al l a el ar ea baj o l a cur va.* La f unci n r eci be el ar ea.*/

    voi d escr i beArea( f l oat ar ea) {pr i nt f ( "\ nEl ar ea baj o l a cur va es %. 8f \ n\ n", ar ea) ;

    }

    Ejercicio sobre Apuntadores como Parmetros de Funciones

    Reescribir el programa que calcula la media de las edades de un grupo de alumnos(Ejercicio 2 sobre funciones, Captulo 6: Funciones) de tal manera que la funcinl eeDat os( ) regrese el nmero de alumnos por el mecanismo de return y la suma de

    edades por parmetro apuntador.

    Arreglos y Apuntadores

    En el Captulo 7: Arreglos se vio que un arreglo es una lista de variables del mismo tipoque se encuentran en localidades contiguas de memoria y que comparten el mismonombre. El hecho de que los elementos de un arreglo se encuentren en localidadescontiguas de memoria permite usar los apuntadores para implementar un mecanismo deacceso a los elementos de un arreglo que, en algunos casos, es ms eficiente que el

    indexamiento.

    Arreglos Unidimensionales y Apuntadores

    Supongamos que deseamos almacenar las calificaciones de un grupo de alumnos y paraello declaramos el arreglo unidimensional:

    i nt cal i f s[50] ;

    Si suponemos que la direccin del arreglo, es decir la direccin de la primera variable delarreglo, cal i f s[0] es 1000. La variable cal i f s[1] tiene la direccin 1004, y as hastala ltima variable cal i f s[49] que tiene la direccin 1196, como se muestra en la figura8-5. Note que como el arreglo es de enteros, las direcciones de las variables seincrementan de cuatro en cuatro.

    Por otro lado, para almacenar las matrculas de esos alumnos podramos declarar elarreglo

    l ong mats[ 50] ;

  • 7/25/2019 Captulo 8 - Apuntadores.pdf

    14/36

    136 Apuntadores

    ITSON Manuel Domitsu Kono

    Si suponemos que la direccin del arreglo mat ses 1200, las direcciones de los elementosdel arreglo sern los mostrados en la figura 8-6. Note que como el arreglo es de enteroslargos, las direcciones de las variables se incrementan de ocho en ocho.

    Figura 8-5

    Figura 8-6

    Mecanismo Interno del Indexamiento para Arreglos Unidimensionales

    En el Captulo 7: Arreglos se vio que el mecanismo de indexamientopermite acceder aun elemento de un arreglo utilizando el nombre del arreglo y su posicin en el arreglo. Estaposicin se conoce como el ndice del elemento. Este mecanismo de indexamiento se

  • 7/25/2019 Captulo 8 - Apuntadores.pdf

    15/36

    Captulo 8 Apuntadores 137

    ITSON Manuel Domitsu Kono

    puede expresar en una segunda forma, la cual utiliza las direcciones de los elementos.Dado que los elementos de un arreglo se encuentran en direcciones contiguas dememoria, podemos expresar la direccin de un elemento en trminos de la direccin delprimer elemento del arreglo o direccin base del arreglo. La direccin de un elemento esigual a la direccin base del arreglo ms un desplazamiento, un entero que representa la

    distancia en nmero de elementos a la que se encuentra el elemento. Para el compilador,el nombre del arreglo representa la direccin base del arreglo . Por ejemplo en elarreglo califs, la direccin del primer elemento es &cal i f s[ 0] o cal i f s + 0 osimplemente cal i f s. La direccin del segundo elemento es &cal i f s[ 1] o cal i f s +1, y la direccin del elemento 50 es &cal i f s[ 49] o cal i f s + 49, tal como se ilustraen la figura 8-7.

    Una vez que se tiene la direccin del elemento podemos accesar al contenido de eseelemento mediante el operador de indireccin. As el acceso al dato almacenado en elprimer elemento del arreglo cal i f s est dado por cal i f s[0] o *cal i f s, el acceso aldato en el segundo elemento es cal i f s[1] o *( cal i f s+1) , y el del ltimo elemento

    por cal i f s[49] o *( cal i f s+49) , tal como se muestra en la figura 8-7.

    Figura 8-7

    En el caso del arreglo mat s, las direcciones y la forma de accesar a los diferentes

    elementos se muestran en la figura 8-8.

    Note que la direccin del elemento cal i f s[0] es cal i f s = 1000 y que la direccin decal i f s[1] es cal i f s+1= 1004. Al sumarle uno a la direccin base del arreglo cal i f svemos que la direccin se aumenta en cuatro bytes, apuntando correctamente al elementoque se encuentra a un elemento de distancia del inicio del arreglo. Como el arreglo mat ses de largos, la direccin del elemento mat s[ 1] es mat s+1= 1208. La razn por la cualla suma se comporta en esta forma "extraa" es que la operacin de suma no es la misma

  • 7/25/2019 Captulo 8 - Apuntadores.pdf

    16/36

    138 Apuntadores

    ITSON Manuel Domitsu Kono

    que la operacin de suma de los nmeros enteros sino es una suma en la aritmtica deapuntadores, y en est aritmtica al sumarle a una direccin un nmero entero n,obtenemos la direccin del elemento que se encuentra a n elementos, del mismo tipo, msadelante.

    Figura 8-8

    El cdigo para sacar el promedio de las calificaciones usando este mtodo de accesar alarreglo sera

    suma = 0;f or ( i = 0; i < nAl ums; i ++) suma += *( cal i f s+i ) ;pr omedi o = ( f l oat ) suma/ nAl ums;

    Las dos formas de indexamiento para acceder a los elementos de un arreglo sonequivalentes y pueden emplearse indistintamente, incluso pueden usarse ambos en elmismo cdigo. En realidad el compilador transforma las expresiones que contienen ndicesen expresiones con direcciones base y desplazamientos. Por ejemplo la expresin

    cal i f s [ i ]

    es transformada por el compilador a

    *(cal i f s+i )

    Acceso a los Elementos de un Arreglo Unidimensional UsandoApuntadores

    Un segundo mecanismo de accesar a los elementos de un arreglo es declarar unapuntador del mismo tipo del arreglo y usar este para que apunte al elemento que nosinteresa. Por ejemplo, el cdigo para sacar el promedio de las calificaciones usando estemtodo de accesar al arreglo sera

  • 7/25/2019 Captulo 8 - Apuntadores.pdf

    17/36

    Captulo 8 Apuntadores 139

    ITSON Manuel Domitsu Kono

    i nt *pCal i f s = cal i f s, *qCal i f s;

    suma = 0;qCal i f s = cal i f s + nAl umnos;f or ( ; pCal i f s < qCal i f s; pCal i f s++) suma += *pCal i f s;

    pr omedi o = ( f l oat ) suma/ nAl umnos;

    En este ejemplo hemos declarado dos apuntadores pCal i f s que apunta al inicio delarreglo cal i f s y qCal i f sque lo hacemos apuntar al siguiente elemento despus de laltima calificacin dentro del arreglo. En la expresin que controla el ciclo

    pCal i f s < qCal i f s

    estamos preguntndonos si la direccin almacenada en pCal i f ses menor (o anterior) ala direccin en qCal i f s. Mientras no hayamos llegado al final de los datos seguiremos enel ciclo. La expresin

    pCal i f s++

    incrementa el valor de la direccin almacenada en pCal i f s en uno, haciendo as queapunte al siguiente elemento del arreglo. Por ltimo en la expresin

    suma += *pCal i f s

    estamos usando el operador de indireccin para accesar al valor almacenado en ladireccin apuntada por pCal i f s, accesando as a los elementos del arreglo.

    Cuando se est procesando un arreglo en forma secuencial, el acceso a los elementos deun arreglo usando este ltimo mtodo es ms eficiente que los dos anteriores. La razn deesto la podemos ver si comparamos los cdigos usados para sumar las calificaciones

    f or ( i = 0; i < nAl ums; i ++) suma += *( cal i f s+i ) ;

    f or ( ; pCal i f s < qCal i f s; pCal i f s++) suma += *pCal i f s;

    Si contamos el nmero de sumas realizadas con el acceso usando ndices veremos quese requieren 3 * nAl umssumas. Mientras que en el mtodo usando apuntadores tenemos2 * nAl umssumas. Por lo que el segundo ciclo se ejecutar ms rpido.

    Si estamos accesando el arreglo en forma aleatoria no hay ventaja en el mtodo deapuntadores y probablemente el mtodo de ndices presente la ventaja de que su notacinsea ms sencilla.

    En C el concepto de arreglo y de apuntador estn ntimamente ligados. De hecho, sitenemos un apuntador podemos indexar a este para accesar a un elemento que seencuentre a una distancia dada de ste. Por ejemplo:

  • 7/25/2019 Captulo 8 - Apuntadores.pdf

    18/36

    140 Apuntadores

    ITSON Manuel Domitsu Kono

    i nt cal i f s[ MAX_GRUPO] , *pCal i f s = cal i f s;. . .

    pCal i f s [5] = 9;

    le asigna 9 al sexto elemento del arreglo cal i f s, tal como lo hara

    cal i f s[5] = 9;

    Un ltimo aspecto que es importante mencionar es establecer la diferencia entre cal i f sy pCal i f s. Al principio ambas apuntan al inicio del arreglo. Sin embargo, cal i f ses unadireccin constante mientras que pCal i f s es una variable apuntador. Por lo tantopodemos hacer lo siguiente

    pCal i f s++;

    pero lo que no podemos hacer es

    cal i f s++

    Aritmtica de Apuntadores

    En las secciones anteriores se estableci que exista una aritmtica de apuntadores cuyasreglas diferan de la aritmtica de los nmeros enteros. Las operaciones vlidas en estaaritmtica y sus reglas son las siguientes:

    A una expresin de tipo apuntador le podemos sumar o restar una expresin entera

    pexp {+| -} nexp

    El resultado de est operacin es la direccin de un elemento del tipo apuntado porpexpy que se encuentra a nexpelementos despus (si el operador es el de suma)

    o antes (si el operador es el de resta) de la direccin dada porpexp. Por ejemplo,

    supongamos que px es un apuntador y n es un entero, entonces las siguientesexpresiones son vlidas

    px + 3px++- - pxpx -= 3 * n

    Podemos restar dos expresiones de tipo apuntador siempre y cuando ambasexpresiones sean del mismo tipo (apunten al mismo tipo de dato).

    pexp2 - pexp1

    Esta operacin da como resultado el nmero de elementos del tipo apuntado porpexp2 ypexp1 que se encuentran entre las direccionespexp2 ypexp1. Por

    ejemplo:

  • 7/25/2019 Captulo 8 - Apuntadores.pdf

    19/36

    Captulo 8 Apuntadores 141

    ITSON Manuel Domitsu Kono

    i nt *px, i nt *py, n;

    . . .n = py - px;

    el valor de n representa el nmero de localidades enteras que hay entre lasdirecciones dadas por pyy px.

    Podemos comparar dos expresiones de tipo apuntador siempre y cuando ambasexpresiones sean del mismo tipo (apunten al mismo tipo de dato).

    pexp1 < pexp2pexp1 pexp2pexp1 >=pexp2pexp1 ==pexp2pexp1 ! =pexp2

    La operacin =da como resultado verdadero (uno) si la direccin dada porpexp1se encuentra despus o es la misma que la direccin dada porpexp2y falso (0) en

    caso contrario.

    La operacin ==da como resultado verdadero (uno) si la direccin dada porpexp1es la misma que la direccin dada porpexp2y falso (0) en caso contrario.

    La operacin ! =da como resultado verdadero (uno) si la direccin dada porpexp1es diferente que la direccin dada porpexp2y falso (0) en caso contrario.

    Ninguna otra operacin es valida con apuntadores.

    Apuntadores a Arreglos Unidimensionales como Parmetros deFunciones

    En el Captulo 7: Arreglos se vio que en C slo se permite que a una funcin se le pase ladireccin de un arreglo. Si la funcin conoce la direccin del arreglo, puede accesar a losdiferentes elementos del arreglo utilizando cualquiera de los dos mtodos ya vistos:

  • 7/25/2019 Captulo 8 - Apuntadores.pdf

    20/36

    142 Apuntadores

    ITSON Manuel Domitsu Kono

    indexamiento o apuntadores. Ya que el parmetro es una direccin, se puede utilizar unapuntador y la sintaxis para el parmetro es la siguiente:

    tipo *nomParArr

    Recuerde que el parmetro slo representa la direccin del arreglo pero no contiene lainformacin sobre el tamao del arreglo. Si se requiere que la funcin conozca el tamaodel arreglo deberemos proporcionrsela a travs de otro parmetro.

    Al igual que en la declaracin de apuntadores, la declaracin de un parmetro querepresenta la direccin de un arreglo puede contener el calificador constpara indicar quela direccin del arreglo, los datos del arreglo o ambos no pueden modificarse. En lasiguiente declaracin

    tipo *constnomParArr

    estamos indicando que dentro de la funcin no podemos alterar el valor del parmetronomParArrel cul representa la direccin del arreglo. Por otro lado la declaracin

    const tipo *nomParArr

    indica que los valores del arreglo apuntado por nomParArrno pueden modificarse. Por

    ltimo, la declaracin

    const tipo *constnomParArr

    indican que dentro de la funcin no podemos alterar el valor del parmetro nomParArr, la

    direccin del arreglo, y que los valores del arreglo apuntado por nomParArr tampoco

    pueden modificarse.

    Al llamar a la funcin, el argumento ser la direccin del arreglo, el cual puede escribirsede cualquiera de las siguientes formas:

    &nomArr[0] nomArr

    La segunda forma es la forma ms empleada. Aunque normalmente al llamar a unafuncin y pasarle la direccin de un arreglo le pasamos la direccin de inicio del arreglo,podemos pasarle la direccin de un subarreglo del arreglo. Por ejemplo podemos llamar ala funcin de las formas siguientes

    &nomArr[3] o nomArr + 3

    para pasarle la direccin del cuarto elemento del arreglo, posiblemente lo que deseamoses que la funcin procese del cuarto elemento del arreglo en adelante.

  • 7/25/2019 Captulo 8 - Apuntadores.pdf

    21/36

    Captulo 8 Apuntadores 143

    ITSON Manuel Domitsu Kono

    Ejemplo sobre Apuntadores a Arreglos Unidimensionales comoParmetros de Funciones

    Crear una funcin que lea las matrculas (nmeros enteros largos) y las calificaciones (tipoenteros) de los alumnos de un grupo y las almacene en dos arreglos unidimensionales. La

    funcin deber leer datos hasta que se de una matrcula cero la cual indica fin de captura.La funcin regresa el nmero de alumnos por el mecanismo de return. La declaracin y ladefinicin de la funcin pedida son:

    i nt l eeDat os( l ong *pMat r i cul as, i nt *pCal i f s, i nt t amMaxGpo) ;

    / ** Est a f unci on l ee l as mat r i cul as y l as cal i f i caci ones de l os al umnos* de un grupo y l os al macena en l os arr egl os apunt ados por pMatr i cul as* y pCal i f s. El t amao maxi mo de l os ar r egl os es de t amMaxGpo. La f unci on* r egr esa el numero de al umnos.*/

    i nt l eeDat os( l ong *pMat r i cul as, i nt *pCal i f s, i nt t amMaxGpo) {i nt n = 0;

    pr i nt f ( "\ nEst e pr ogr ama l ee l as mat r i cul as y l as cal i f i caci ones") ;pr i nt f ( "\ nde un gr upo. El pr ograma or dena l os dat os por l a mat r i cul a") ;pr i nt f ( "\ ny l os despl i ega. El pr ogr ama t ambi en per mi t e consul t ar ") ;pr i nt f (" \ nl a cal i f i caci on por mat r i cul a. \ n") ;

    whi l e ( 1) {/ / Ver i f i ca si hay espaci o en l os ar r egl osi f ( n >= t amMaxGpo) {

    pri nt f (" \ nArr egl os l l enos");br eak;

    }

    / / Lee una matr i cul apr i nt f ( "\ nMat r i cul a del al umno %d, 0 par a t er mi nar : ", n + 1) ;

    scanf ( "%l d", pMat r i cul as) ;

    / / Si l a mat r i cul a l ei da es cer o t ermi nai f ( *pMat r i cul as == 0) br eak;

    / / Lee l a cal i f i caci onpr i nt f ( "\ nCal i f i caci on del al umno %d: ", n + 1) ;scanf ( "%d", pCal i f s);

    / / Si gui ent e al umnon++;pMatr i cul as++;pCal i f s++;

    }

    / / Regresa el numero de al umnosr et ur n n;}

    Ejercicios sobre arreglos unidimensionales

    1. Crear una funcin que despliegue el contenido de los arreglos del ejemplo 1. Utiliceel mecanismo de apuntadores para acceder a los elementos de los arreglos.

  • 7/25/2019 Captulo 8 - Apuntadores.pdf

    22/36

    144 Apuntadores

    ITSON Manuel Domitsu Kono

    2. Crear una funcin que busque secuencialmente una matrcula en el arreglo dematrculas del ejemplo 1. La funcin deber regresar un entero, la posicin de lamatrcula si la encontr o -1 si no se encuentra. Utilice el mecanismo deapuntadores para acceder a los elementos de los arreglos.

    Arreglos Multidimensionales y Apuntadores

    En el Captulo 7: Arreglos se vio que un arreglo en dos dimensiones es un arreglo dearreglos de una dimensin y que puede visualizarse como una tabla o matriz, mientrasque un arreglo en tres dimensiones es un arreglo de tablas. Por ejemplo para almacenarlas cuatro calificaciones parciales de un grupo de alumnos podramos declarar el arreglo:

    i nt cal Par s[ 50] [ 4]

    que declara un arreglo llamado cal Par s formado por 50 variables (una para cada

    alumno) que a su vez son arreglos de 4 elementos de tipo int (las calificaciones). Otraforma de ver al arreglo es como una tabla con 50 filas (los alumnos) y con cuatrocolumnas (las calificaciones) en cada fila. Esta declaracin nos crea 200 variables comose muestran en la figura 8-9. En realidad, la figura 8-9 slo es una representacin delarreglo. En la memoria de la computadora, el arreglo se encuentra como se muestra en lafigura 8-10. Note que los elementos se encuentran ordenados por filas. Primero loselementos en la primera fila, luego los de la segunda fila, etc.

    Figura 8-9

    Por otro lado, supongamos que deseamos almacenar las ventas por semestre de unacompaa que est establecida en tres ciudades, con cuatro sucursales en cada ciudad.Para esto podemos declarar el arreglo vent as

    f l oat vent as[3] [ 4] [ 2] ;

    como formado por 3 variables (las ciudades) que a su vez son arreglos en dosdimensiones. Cada uno de los elementos es un arreglo de 4 (sucursales) por 2 elementos

  • 7/25/2019 Captulo 8 - Apuntadores.pdf

    23/36

    Captulo 8 Apuntadores 145

    ITSON Manuel Domitsu Kono

    (semestres) de tipo float. Otra forma de ver al arreglo es como uno formado de 3 tablas(las ciudades), cada una con 4 filas (las sucursales) y cada fila con 2 columnas (lossemestres). Esta declaracin nos crea 24 variables tal como se muestran en la figura 8-11.

    Figura 8-10

    Figura 8-11

    Al igual que con los arreglos en dos dimensiones, en los arreglos en tres dimensiones loselementos se encuentran ordenados primero por tablas y luego por filas, tal como semuestra en la figura 8-12.

    Mecanismo Interno del Indexamiento para ArreglosMultidimensionales

    Al igual que con los arreglos en una dimensin, el mecanismo de indexamiento para losarreglos multidimensionales se puede expresar en trminos de las direcciones de loselementos. Un arreglo en dos dimensiones es un arreglo de arreglos. El nombre de cada

  • 7/25/2019 Captulo 8 - Apuntadores.pdf

    24/36

    146 Apuntadores

    ITSON Manuel Domitsu Kono

    arreglo est compuesto del nombre del arreglo completo y su posicin en ste. Porejemplo el arreglo cal Par ses un arreglo de 50 arreglos y sus nombres son

    cal Pars[0] , cal Pars[ 1] , . . . , cal Pars[ 49]

    Figura 8-12

    Como cal Par s[ 0] es el nombre del arreglo que contiene las calificaciones del primeralumno, cal Par s[ 0] representa la direccin de ese arreglo o fila. cal Par s[ 1] representa la direccin de la segunda fila, etc, tal como se muestra en la figura 8-13.

    En un arreglo unidimensional, el acceso a un elemento por indexamiento se puede escribir

    de dos formas, por ejemplo en el arreglo cal i f s de la figura 8-7, cal i f s[ i ] esequivalente a *(cal i f s+i ) . Por consistencia, en un arreglo en dos dimensiones lasdirecciones de las filas tambin se pueden escribir como:

    *( cal Pars+1) , *( cal Par s+2) , . . . , *( cal Par s+49)

    como se muestran en la figura 8-13.

  • 7/25/2019 Captulo 8 - Apuntadores.pdf

    25/36

    Captulo 8 Apuntadores 147

    ITSON Manuel Domitsu Kono

    Figura 8-13

    Cada elemento de un arreglo en dos dimensiones, tiene tambin una direccin. Estadireccin se puede establecer a partir de la direccin de la fila en la que se encuentra elelemento. Como la fila constituye un arreglo unidimensional, la direccin del elemento esla direccin base de la fila ms el desplazamiento del elemento. Por ejemplo en el arreglocal Par s, figura 8-13, la direccin del j-simo elemento de la fila i es

    cal Par s[i ] +j *( cal Par s+i ) +j

    Si a esta direccin le aplicamos el operador de indireccin obtenemos el acceso a dichoelemento. Luego el elemento cal Pars[ i ] [ j ] puede accesarse mediante

    *( cal Pars[ i ] +j ) *( *( cal Pars+i ) +j )

    En forma similar, el arreglo ventas es un arreglo de arreglos en dos dimensiones o tablas.Los nombres de las tablas son

    vent as[ 0] , vent as [ 1] y vent as[ 2]

    Estos nombres son las direcciones de cada plano y pueden escribirse, por similitud a los

    arreglos unidimensionales, como

    *( vent as+0) , *( vent as+1) y *( vent as+2)

    tal como se muestra en la figura 8-14. Cada una de las tablas est formada por un arreglode 4 filas. Estas filas tienen su nombre. Por ejemplo la fila j del plano i tiene el nombre

    ventas[ i ] [ j ]

  • 7/25/2019 Captulo 8 - Apuntadores.pdf

    26/36

    148 Apuntadores

    ITSON Manuel Domitsu Kono

    Figura 8-14

    Para mantener una consistencia con la notacin empleada en los arreglos de dosdimensiones, el nombre de la fila anterior, puede escribirse de las siguientes otras formas

    *( vent as[i ] +j ) o *( *( vent as+i ) +j )

    El nombre de cada fila es la direccin de la fila. Tambin cada elemento del arreglo tienesu direccin, esta se puede formar a partir de la direccin de la fila. Por ejemplo elelemento k de la fila j de la tabla i del arreglo tiene la direccin dada por

    vent as[ i ] [ j ] +k o *( vent as[ i ] +j ) +k o *( *( vent as+i ) +j ) +k

    Por ltimo, el acceso a los elementos del arreglo se obtiene aplicndole el operador deindireccin a cualquiera de las formas de expresar la direccin de un elemento. Luego elelemento ventas[ i ] [ j ] [ k] puede accesarse mediante

    *( vent as[ i ] [ j ] +k) o *( *( vent as[ i ] +j ) +k) o *( *( *( vent as+i ) +j ) +k)

    Las diferentes formas descritas anteriormente para accesar a los elementos de un arreglomultidimensional son equivalentes y pueden emplearse indistintamente, incluso pueden

    usarse mezcladas en el mismo cdigo. Estas formas construyen la direccin de unelemento a partir de la direccin de la fila y sta ltima direccin a partir de la direccin deuna tabla, etc.

    Por ejemplo el siguiente cdigo nos permite calcular el promedio de las calificaciones decada alumno y la calificacin promedio del grupo:

    i nt cal Pars[ 50] [ 4] ;i nt i , j , suma, nAl ums;

  • 7/25/2019 Captulo 8 - Apuntadores.pdf

    27/36

    Captulo 8 Apuntadores 149

    ITSON Manuel Domitsu Kono

    f l oat promedi os[50] , sumaT, pr omedi oT;. . .sumaT = 0;

    / / Par a cada al umnof or ( i = 0; i < nAl ums; i ++) {

    / / I ni ci al i za el acumul ador de cal i f i caci ones del al umnosuma = 0;

    / / Acumul a l as cal i f i caci ones del al umnof or ( j = 0; j < 4; j ++) suma += *( *( cal Par s+i ) +j ) ;

    / * Cal cul a el promedi o del al umno y al macnal oen el arr egl o pr omedi os */

    *( pr omedi os+i ) = ( f l oat ) suma/ 4;

    / / Acumul a el promedi osumaT += *( promedi os+i ) ;

    }/ / Cal cul a el promedi o gl obal de l os al umnospromedi oT = sumaT/ nAl ums;

    Otra alternativa es construir la direccin de un elemento a partir de la direccin base delarreglo y del desplazamiento de dicho elemento con respecto al inicio del arreglo. Estatcnica se basa en el hecho de que los arreglos multidimensionales se encuentran en lamemoria de la computadora acomodados como una lista en una dimensin, tal como semuestra en las figuras 8-10 y 8-12.

    Considerando a los arreglos multidimensionales como lineales, la direccin de unelemento se formara a partir de la direccin base del arreglo ms un desplazamiento. Ladireccin base de un arreglo multidimensional es la direccin de su primer elemento. Estadireccin, a diferencia de los arreglos unidimensionales no est dada por el nombre delarreglo. En un arreglo en dos dimensiones el nombre del arreglo, por s solo, constituye la

    direccin de la primera fila del arreglo y aunque la direccin del primer elemento delarreglo y la direccin de la primera fila son numricamente iguales, conceptualmente sondiferentes. La razn de esto est dada por forma en que opera la aritmtica deapuntadores.

    Por ejemplo considere el arreglo cal Par s. Tanto &cal Par s[ 0] [ 0] como cal Par svalen 1200 (la direccin de inicio del arreglo), sin embargo &cal par s[ 0] [ 0] +1 vale1204 (la direccin del siguiente elemento del arreglo) mientras cal pars+1vale 1216 (ladireccin de la siguiente fila del arreglo).

    De la misma manera, en un arreglo en tres dimensiones el nombre del arreglo, por s solo,

    constituye la direccin de la primera tabla del arreglo y no del primer elemento del arreglo,aunque stas sean numricamente iguales. Por ejemplo en el arreglo ventas, tanto&vent as[ 0] [ 0] [ 0] como ventas valen 1500 (la direccin de inicio del arreglo), sinembargo &vent as[ 0] [ 0] [ 0] +1 vale 1504 (la direccin del siguiente elemento delarreglo) mientras ventas+1vale 1532 (la direccin de la siguiente tabla del arreglo).

  • 7/25/2019 Captulo 8 - Apuntadores.pdf

    28/36

    150 Apuntadores

    ITSON Manuel Domitsu Kono

    Para determinar el desplazamiento de un elemento de un arreglo multidimensional conrespecto al inicio del arreglo tenemos que considerar que el arreglo en la memoria eslineal y que debemos de contar todos los elementos que se encuentran entre el elementodado y el primer elemento del arreglo. Por ejemplo, en un arreglo de dos dimensiones, eldesplazamiento del elemento que se encuentra en la fila i, columna j est dado por

    i * numCol s + j

    donde numCol s es el nmero de columnas en el arreglo. En un arreglo de tresdimensiones, el desplazamiento del elemento que se encuentra en la tabla i, fila j, columnak est dado por

    i * numFi l as * numCol s + j * numCol s + k

    donde numFi l as es el nmero de filas y numCol s es el nmero de columnas en elarreglo. Por ejemplo el siguiente cdigo nos permite calcular el promedio de lascalificaciones de cada alumno y la calificacin promedio del grupo:

    i nt cal Pars[ 50] [ 4] ;i nt i , j , suma;f l oat promedi os[50] , sumaT, pr omedi oT;. . .sumaT = 0;

    / / Par a cada al umnof or ( i = 0; i < nAl ums; i ++) {

    / / I ni ci al i za el acumul ador de cal i f i caci ones del al umnosuma = 0;

    / / Acumul a l as cal i f i caci ones del al umnof or ( j = 0; j < 4; j ++)

    suma += &cal Par s[ 0] [ 0] + 4*i +j ;

    / * Cal cul a el promedi o del al umno y al macnal oen el arr egl o pr omedi os */

    *( pr omedi os+i ) = ( f l oat ) suma/ 4;

    / / Acumul a el promedi osumaT += *( promedi os+i ) ;

    }

    / / Cal cul a el promedi o gl obal de l os al umnospromedi oT = sumaT/ nAl ums;

    Acceso a los Elementos de un Arreglo Multidimensional Usando

    Apuntadores

    El mecanismo de apuntadores empleado para accesar a los elementos de un arreglounidimensional puede emplearse en el caso de arreglos multidimensionales. Podemosdeclarar un apuntador al mismo tipo que el tipo base del arreglo e inicializarlo a ladireccin base del arreglo. Incrementando este apuntador podemos hacer que apunte alos diferentes elementos del arreglo. Por ejemplo, el siguiente cdigo es una variante delejemplo anterior.

  • 7/25/2019 Captulo 8 - Apuntadores.pdf

    29/36

    Captulo 8 Apuntadores 151

    ITSON Manuel Domitsu Kono

    i nt cal Par s[ 50] [ 4] , *pCal Par s, *qCal Par s;i nt i , suma;f l oat promedi os[50] , sumaT, pr omedi oT, *ppr om= pr omedi os;. . .suma = 0;sumaT = 0;

    / / Apunt ador al i ni ci o del ar r egl opCal Par s = &cal Par s[ 0] [ 0] ;

    / * Apunt ador a l a si gui ent e l ocal i dad despus delf i nal del arr egl o + 1 */

    qCal Par s = &cal Par s[ nAl ums] [ 0] ;

    f or ( i = 0 ; pCal Par s < qCal Par s; pCal Par s++, i ++) {/ / Acumul a l as cal i f i caci ones de un al umnosuma += *pCal Par s;

    / / Si ya se acumul aron l as cal i f i caci ones de un al umnoi f ( i % 4 == 3) {

    / / Cal cul a el promedi o de ese al umno

    *ppr om = ( f l oat ) suma/ 4;/ / Acumul a el promedi osumaT += *pprom;

    ppr om++;suma = 0;

    }}

    / / Cal cul a el promedi o gl obal de l os al umnospromedi oT = sumaT/ nAl ums;

    En el cdigo anterior, en la asignacin

    pCal Par s = &cal Par s[ 0] [ 0] ;

    hacemos que pCalPars apunte al inicio del arreglo. Si hubisemos escrito

    pCal Par s = cal Par s;

    el compilador generara una advertencia, ya que pCal Par s es un apuntador a int ycal Par s, por ser el nombre de un arreglo en dos dimensiones, es la direccin de unarreglo de arreglos y que aunque apuntan a la misma direccin son direcciones a diferentetipo. Sin embargo como en una asignacin el tipo resultante es el de la variable de laizquierda, la direccin cal Par ses convertida a una direccin a entero. El resultado es de

    que pCal Pars si apunta a la direccin base del arreglo, aunque el compilador nosadvierte que hemos hecho una operacin sospechosa y que pudiera ser errnea.Podemos evitar la advertencia del compilador haciendo clara nuestra intencin del cambiode tipo de la direccin, usando el operador cast

    pCal Pars = ( i nt *) cal Pars;

  • 7/25/2019 Captulo 8 - Apuntadores.pdf

    30/36

    152 Apuntadores

    ITSON Manuel Domitsu Kono

    Aqu, estamos convirtiendo explcitamente, el tipo apuntado por cal Par sa un apuntadora entero.

    Apuntadores a Arreglos Multid imensionales como Parmetros deFunciones

    En el Captulo 7: Arreglos se vio que a una funcin slo le podemos pasar la direccin deun arreglo multidimensional. Si el arreglo es en dos dimensiones la declaracin delparmetro tendr la siguiente forma:

    tipo nomParArr[][numCols]

    Para un arreglo en tres dimensiones sera

    tipo nomParArr[][numFilas][numCols]

    Las declaraciones correspondientes usando apuntadores seran:

    tipo *nomParArr[numCols]

    Para un arreglo en dos dimensiones, y

    tipo *nomParArr[numFilas][numCols]

    Para un arreglo en tres dimensiones.

    Ambas declaraciones del parmetro que corresponde a la direccin del arreglo en dosdimensiones slo proporcionan la direccin del arreglo y su nmero de columnas. Si se

    requiere que la funcin conozca el nmero de filas deberemos proporcionrsela a travsde otro parmetro. En el caso del arreglo en tres dimensiones, las declaraciones sloproporcionan la direccin del arreglo y sus nmeros de filas y columnas. Si se requiereque la funcin conozca el nmero de tablas deberemos proporcionrsela a travs de otroparmetro.

    Al llamar a la funcin, el argumento ser slo el nombre del arreglo,

    nomArr

    Otra alternativa para declarar el parmetro que corresponde a la direccin de un arreglo

    multidimensional es la siguiente

    tipo *nomParArr

    En este caso el parmetro slo proporciona la direccin del base del arreglo y deberemosutilizar otros parmetros para pasarle a la funcin las dimensiones del arreglo. Adems eneste caso la direccin de los elementos debe calcularse usando el mecanismo deapuntadores.

  • 7/25/2019 Captulo 8 - Apuntadores.pdf

    31/36

    Captulo 8 Apuntadores 153

    ITSON Manuel Domitsu Kono

    En este caso, al llamar a la funcin, el argumento ser la direccin base del arreglo,

    &nomArr[0][0]

    en el caso de un arreglo en dos dimensiones

    &nomArr[0][0][0]

    en el caso de un arreglo en tres dimensiones, etc.

    Ejemplo sobre arreglos multidimensionales

    Una agencia de autos usados se especializa en automviles Volkswagen de los siguientestipos: Pointer, Golf y Jetta. Adems slo maneja los modelos de los tres aos recientes.

    1. Para tener el control del inventario, el dueo guarda en un arreglo de dosdimensiones, el nmero de automviles que posee. Escribe una funcin llamadaleeAutos() que permita capturar el inventario inicial del lote y lo almacene en unarreglo. La funcin recibe como parmetro la direccin del arreglo en el que se va aalmacenar los datos.

    Si el parmetro representa un apuntador al arreglo en dos dimensiones, ladeclaracin y la definicin de la funcin pedida pueden ser

    / * Const ant e que r epresent a el model o de auto ms vi ej ovendi do en l a agenci a */

    const i nt VI EJ O = 2007;

    / / Decl ar aci n de l a f unci n l eeAut os( )voi d l eeAut os( i nt *pAut os[ 3] ) ;

    / / Def i ni ci n de l a f unci n l eeAut os( )/ ** Est a f unci n l ee el nmero de autos de cada marca y* model o de l a agenci a de aut os usados y l os al macena* en el arr egl o apunt ado por pAut os.*/

    voi d l eeAut os( i nt ( *pAut os) [ 3] ) {i nt marca, model o;

    / / Par a cada marca de aut of or ( marca = 0; marca < 3; marca++) {

    / / Par a cada model o

    f or ( model o = 0; model o < 3; model o++) {/ / Despl i ega l a mar caswi t ch (marca) {

    case 0: pr i nt f ( "\ nAut os Poi nt er , ") ;br eak;

    case 1: pri nt f ( "\ nAut os Gol f , ") ;br eak;

    case 2: pri nt f ( "\ nAut os J et t a, ") ;}/ / Despl i ega el model opr i nt f ( "model o %d: ", VI EJ O + model o) ;

  • 7/25/2019 Captulo 8 - Apuntadores.pdf

    32/36

    154 Apuntadores

    ITSON Manuel Domitsu Kono

    / / Lee l a cant i dad de aut os de l a marca y model oscanf ( "%d", pAutos[ marca] +model o) ;

    }}

    }

    Por otro lado, si el parmetro de la funcin, slo representa la direccin base delarreglo, la declaracin y la definicin de la funcin pedida pueden ser

    / * Const ant e que r epresent a el model o de auto ms vi ej ovendi do en l a agenci a */

    const i nt VI EJ O = 2007;

    / / Decl ar aci n de l a f unci n l eeAut os( )voi d l eeAut os( i nt *pAut os) ;

    / / Def i ni ci n de l a f unci n l eeAut os( )/ ** Est a f unci n l ee el nmero de autos de cada marca y* model o de l a agenci a de aut os usados y l os al macena

    * en el arr egl o apunt ado por pAut os.*/voi d l eeAut os( i nt *pAut os) {

    i nt marca, model o;

    / / Par a cada marca de aut of or ( marca = 0; marca < 3; marca++) {

    / / Par a cada model of or ( model o = 0; model o < 3; model o++) {

    / / Despl i ega l a mar caswi t ch (marca) {

    case 0: pr i nt f ( "\ nAut os Poi nt er , ") ;br eak;

    case 1: pri nt f ( "\ nAut os Gol f , ") ;br eak;

    case 2: pri nt f ( "\ nAut os J et t a, ") ;}/ / Despl i ega el model opr i nt f ( "model o %d: ", VI EJ O + model o) ;

    / / Lee l a cant i dad de aut os de l a marca y model oscanf ( "%d", pAut os + 3*marca + model o) ;

    }}

    }

    2. A fin de saber la inversin que tiene en la agencia, el dueo guarda en otro arreglo,el monto que pago por cada automvil (Supongamos que por todos los autos delmismo tipo y del mismo modelo pag lo mismo). Escribe una funcin llamada

    leeMontos() que permita capturar el monto pagado por cada automvil y loalmacene en un arreglo. La funcin recibe como parmetro la direccin del arregloen que se va a almacenar los datos.

    Si el parmetro representa un apuntador al arreglo en dos dimensiones, ladeclaracin y la definicin de la funcin pedida pueden ser

    / / Decl ar aci n de l a f unci n l eeMont os( )

  • 7/25/2019 Captulo 8 - Apuntadores.pdf

    33/36

    Captulo 8 Apuntadores 155

    ITSON Manuel Domitsu Kono

    voi d l eeMont os( f l oat *pMont os[ 3] ) ;/ / Def i ni ci n de l a funci n l eeMont os( )/ ** Est a f unci n l ee el cost o de cada aut o para cada marca y* model o de l a agenci a de aut os usados y l os al macena* en el arr egl o apunt ado por pMont os.*/

    voi d l eeMont os( f l oat ( *pMont os) [ 3] ) {i nt marca, model o;

    / / Par a cada marca de aut of or ( marca = 0; marca < 3; marca++) {

    / / Par a cada model o */f or ( model o = 0; model o < 3; model o++) {

    / / Despl i ega l a mar caswi t ch (marca) {

    case 0: pr i nt f ( "\ nAut os Poi nt er , ") ;br eak;

    case 1: pri nt f ( "\ nAut os Gol f , ") ;br eak;

    case 2: pri nt f ( "\ nAut os J et t a, ") ;}

    / / Despl i ega el model opr i nt f ( "model o %d: ", VI EJ O + model o) ;

    / / Lee l os mont os de l os aut os de l a marca y model oscanf ( "%f ", pMont os[ marca]+model o) ;

    }}

    }

    Por otro lado, si el parmetro de la funcin, slo representa la direccin base delarreglo, la declaracin y la definicin de la funcin pedida pueden ser

    / / Decl ar aci n de l a f unci n l eeMont os( )

    voi d l eeMont os( f l oat *pMont os) ;/ / Def i ni ci n de l a funci n l eeMont os( )/ ** Est a f unci n l ee el cost o de cada aut o para cada marca y* model o de l a agenci a de aut os usados y l os al macena* en el arr egl o apunt ado por pMont os.*/

    voi d l eeMont os( f l oat *pMont os) {i nt marca, model o;

    / / Par a cada marca de aut of or ( marca = 0; marca < 3; marca++) {

    / / Par a cada model o */f or ( model o = 0; model o < 3; model o++) {

    / / Despl i ega l a mar caswi t ch (marca) {

    case 0: pr i nt f ( "\ nAut os Poi nt er , ") ;br eak;

    case 1: pri nt f ( "\ nAut os Gol f , ") ;br eak;

    case 2: pri nt f ( "\ nAut os J et t a, ") ;}/ / Despl i ega el model opr i nt f ( "model o %d: ", VI EJ O + model o) ;

  • 7/25/2019 Captulo 8 - Apuntadores.pdf

    34/36

    156 Apuntadores

    ITSON Manuel Domitsu Kono

    / / Lee l os mont os de l os aut os de l a marca y model oscanf ( "%f ", pMont os + 3*marca + model o) ;

    }}

    }

    Ejercicios sobre arreglos multidimensionales

    1. Haga una funcin llamada mont oTotal ( ) que devuelva el monto total invertido enel inventario del lote. La funcin recibe como parmetros las direcciones de losarreglos que contienen el nmero de autos y sus costos. En esta funcin utilice comoparmetros apuntadores a los arreglos en dos dimensiones.

    2. Modifique la funcin del ejercicio 1 para que el parmetro slo contenga la direccindel arreglo sin la informacin de las columnas del arreglo.

    Problemas1. Cree una funcin que reciba un entero largo que represente el nmero de

    segundos transcurrido desde las 0:00:00 y que regrese la hora del da en tresenteros que representen las horas, minutos y segundos, respectivamente.

    2. Escribe la salida que tendra el siguiente programa.

    #i ncl ude voi d f 1( i nt *u, i nt *d, i nt *t) ;

    voi d f 2( i nt *n1, i nt *n2) ;i nt mai n( voi d) {

    i nt x, y, z;

    x = 90; y = 25; z = 50;f 1( &x, &y, &z) ;pr i nt f ( "\ n%d %d %d", x, y, z) ;x = 6; y = 2; z = 1;f 1( &x, &y, &z) ;pr i nt f ( "\ n%d %d %d", x, y, z) ;r et ur n 0;

    }

    voi d f 1( i nt *u, i nt *d, i nt *t) {i f ( *u > *d) f 2(u, d) ;i f ( *d > * t ) {

    f2 (d , t ) ;i f ( *u > *d) f 2(u, d) ;

    }}

    voi d f 2( i nt *n1, i nt *n2) {i nt t = *n1;

    *n1 = *n2;

  • 7/25/2019 Captulo 8 - Apuntadores.pdf

    35/36

    Captulo 8 Apuntadores 157

    ITSON Manuel Domitsu Kono

    *n2 = t;}

    3. Cree una funcin que reciba como parmetros dos apuntadores a nmerosenteros. Esos nmeros representan el numerador y denominador de un nmerofraccionario. La funcin deber reducir ese nmero fraccionario a su equivalente

    mas simple y regresar el nmero fraccionario de la misma forma que lo recibi. Porejemplo el equivalente ms simple del nmero 24/120 es 1/5. Sugerencia: Lafuncin puede llamar a la funcin que calcula el mximo comn divisor de dosnmeros, del problema 3 del Captulo 6: Funciones.

    4. a) Cree una funcin que reciba como parmetros dos apuntadores a nmerosenteros y cuatro enteros. Los cuatro enteros representan dos nmerosfraccionarios tal como se explic en el problema anterior. La funcin debersumar las fracciones y regresar su equivalente ms simple a travs de los dosparmetros apuntador. b) Repita el inciso a) para la resta, multiplicacin ydivisin de fracciones.

    5. Crea un programa que permita el despliegue de una tabla de conversin de C a Fo de F a C. El programa deber tener al menos cuatro funciones:

    Una que pregunte el tipo de conversin deseada. El usuario teclear 'c' o 'C' si laconversin va a ser de C a F y 'f' o 'F' si la conversin es de F a C. La funcindeber regresar el carcter ledo por el mecanismo de return.

    Otra funcin que pregunte el rango de valores de la tabla y el incremento. Lafuncin recibir como parmetros las direcciones de las variables donde sealmacenarn estos datos.

    Otras dos funciones para desplegar cada tipo de tabla de conversin.

    6. Escribe el cdigo de un programa, que realice las cuatro operacionesfundamentales de la aritmtica sobre fracciones. El programa deber ser capaz derealizar operaciones consecutivas, mostrando los resultados parciales. Sideseamos que el programa termine presionaremos la tecla '=', en lugar deloperador.

    Una primera aproximacin al pseudocdigo es:

    lee r esul t ado / / Pr i mer nmer o f r acci onar i olee operadormientras(operador != ' =' ) {

    lee operando / / Si gui ent e nmer o f r acci onari ocal cul a resul t adoescribe r esul t adolee operador

    }

  • 7/25/2019 Captulo 8 - Apuntadores.pdf

    36/36

    158 Apuntadores

    Los nmeros fraccionarios debern leerse y desplegarse en el formato natural, estoes, tal como la escribimos normalmente, por ejemplo:

    2/3

    Use las funciones desarrolladas en el problema 4.

    7. En el contexto de la declaracin:

    f l oat t abl a[ 10] , *pt , *qt ;

    Cul es el efecto de las siguientes declaraciones y proposiciones?

    pt = tabl a;*pt = 0;*(pt + 2) = 3. 14;qt = t abl a + 10;pri nt f ( "\ n%d", qt - pt ) ;

    8. Modifique el programa del problema 1 (del final del captulo) del Captulo 7:Arreglos para que el acceso a los elementos de los arreglos sea medianteapuntadores en lugar de ndices.

    9. Modifique el programa del problema 2 (del final del captulo) del Captulo 7:Arreglos para que el acceso a los elementos de los arreglos sea medianteapuntadores en lugar de ndices.

    10. Modifique el programa del problema 3 (del final del captulo) del Captulo 7:Arreglos para que el acceso a los elementos de los arreglos sea mediante

    apuntadores en lugar de ndices.

    11. Modifique el programa del problema 4 (del final del captulo) del Captulo 7:Arreglos para que el acceso a los elementos de los arreglos sea medianteapuntadores en lugar de ndices.