Herramientas de usuario

Herramientas del sitio


arreglos

Diferencias

Muestra las diferencias entre dos versiones de la página.

Enlace a la vista de comparación

Ambos lados, revisión anteriorRevisión previa
Próxima revisión
Revisión previa
arreglos [2012/08/03 15:55] – [Arreglos globales] lmateuarreglos [2016/09/27 13:02] (actual) – [Arreglos globales] lmateu
Línea 1: Línea 1:
 ===== Arreglos ===== ===== Arreglos =====
  
-En realidad C no posee verdaderos arreglos como ocurre en Java.  En C un arreglo de n elementos de un tipo T corresponde a un puntero al comienzo de un área de memoria que contiene n variables consecutivas de tipo T.  De modo que lo que se vió en el capítulo sobre punteros es el 90% de lo que se puede escribir sobre arreglos.+En realidad C no posee verdaderos arreglos como los de Java.  En C un arreglo de n elementos de un tipo T corresponde a un puntero al comienzo de un área de memoria que contiene n variables consecutivas de tipo T.  De modo que lo que se vió en el capítulo sobre punteros es el 90% de lo que se puede escribir sobre arreglos.
  
-El otro 10% corresponde la declaración de arreglos de tamaño constante.  La idea con estos arreglos es evitar tener que llamar a malloc para ubicarlos en el heap.  El espacio en memoria se asigna ya sea en el área de variables globales, la pila o el heap según el contexto en que se declaran.+El otro 10% corresponde la declaración de arreglos de tamaño constante.  La idea con estos arreglos es evitar tener que llamar a malloc para ubicarlos en el heap.  El espacio en memoria se asigna ya sea en el área de variables globales, la pila o el heap según el contexto en que se declaran.
  
 ==== Arreglos globales ==== ==== Arreglos globales ====
Línea 23: Línea 23:
 </code> </code>
  
-El primero es un arreglo de 100 elementos inicializados por omisión en 0.  El tipo de la expresión //a// es //double*// y corresponde a la dirección del primer elemento de un área de memoria global con espacio para 100 variables consecutivas de tipo double.  Su tiempo de vida y alcance es el mismo de todas las variables globales, es decir su memoria se asigna al iniciarse el proceso y solo se libera al terminar el proceso.  No se le asigna espacio con malloc.  Se accede a sus elementos con la notación //p[i]// o bien //*(p+i)// Es decir es equivalente escribir ''*(a+i)= *(a-i-1) + *(a-i-2);''.+El primero es un arreglo de 100 elementos inicializados por omisión en 0.  El tipo de la expresión //a// es //double*// y corresponde a la dirección del primer elemento de un área de memoria global con espacio para 100 variables consecutivas de tipo double.  Su tiempo de vida y alcance es el mismo de todas las variables globales, es decir su memoria se asigna al iniciarse el proceso y solo se libera al terminar el proceso.  No se le asigna espacio con malloc.  Se accede a sus elementos con la notación //p[i]// o bien //*(p+i)// Es decir el cuerpo del ciclo for es equivalente ''*(a+i)= *(a-i-1) + *(a-i-2);''.
  
 En este caso //a// **no es una variable**.  Es un error asignar una nueva dirección a //a// como en: En este caso //a// **no es una variable**.  Es un error asignar una nueva dirección a //a// como en:
Línea 29: Línea 29:
   a= (double*)malloc(100*sizeof(double)); /* Esto es un error */   a= (double*)malloc(100*sizeof(double)); /* Esto es un error */
      
-En este caso el identificador //a// representa una constante con la dirección del primer elemento del arreglo en memoria y por eso el compilador reclama porque no se puede cambiar una constante.  Esto queda representado en la siguiente figura:+En este caso el identificador //a// representa una constante correspondiente a la dirección del primer elemento del arreglo en memoria y por eso el compilador reclama porque no se puede cambiar una constante.  Esto queda representado en la siguiente figura:
  
-El arreglo b corresponde a un arreglo de 4 elementos preinicializados con constantes conocidas en tiempo de compilación.  El arreglo c también es un arreglo preinicializado solo que el compilador infiere el tamaño del arreglo contando la cantidad de elementos que aparecen en las llaves, en este caso 3.  Por último el arreglo s corresponde al mismo caso que c.  En la próxima sección veremos que s es en realidad un string.+{{ :arreglos_globales.png?nolink&400 |}} 
 + 
 +Volviendo al código de arriba, el arreglo b corresponde a un arreglo de 4 elementos preinicializados con constantes conocidas en tiempo de compilación.  El arreglo c también es un arreglo preinicializado solo que el compilador infiere el tamaño del arreglo contando la cantidad de elementos que aparecen en las llaves, en este caso 3.  Por último el arreglo s corresponde al mismo caso que c.  En la próxima sección veremos que s es en realidad un string.
  
 Nótese que el compilador no genera ningún código para inicializar los arreglos globales.  Los valores iniciales van directamente en el archivo binario que genera el compilador.  Por eso es importante que los valores iniciales sean valores constantes o expresiones constantes, es decir que el compilador puede evaluar. Nótese que el compilador no genera ningún código para inicializar los arreglos globales.  Los valores iniciales van directamente en el archivo binario que genera el compilador.  Por eso es importante que los valores iniciales sean valores constantes o expresiones constantes, es decir que el compilador puede evaluar.
  
-=== Inicialización de punteros ===+=== Inicialización de punteros globales ===
  
 Las siguientes declaraciones globales son válidas: Las siguientes declaraciones globales son válidas:
Línea 42: Línea 44:
 int x, y; int x, y;
 int *p= &x; int *p= &x;
-int *p[]= {&x, &y};+int *q[]= {&x, &y};
 </code> </code>
  
-En este caso //&x// y //&y// se considera constantes.  En realidad el compilador no puede determinar su valores pero a la larga sí se puede determinar esa dirección antes de comenzar la ejecución del programa.  Existen mecanismos especiales en el compilador y en el linker para poder dar un valor inicial correcto en este caso.+En este caso //&x// y //&y// se considera constantes.  En realidad el compilador no puede determinar sus valores pero a la larga sí se puede determinar esa dirección antes de comenzar la ejecución del programa.  Existen mecanismos especiales en el compilador y en el linker para poder dar un valor inicial correcto en este caso.
 ==== Arreglos automáticos ==== ==== Arreglos automáticos ====
  
-También es posible declarar un arreglo local a una función.  El tiempo de vida y alcance es el mismo de todas las variables automáticas.  Por ejemplo:+También es posible declarar un arreglo local a una función.  El tiempo de vida y alcance es el mismo de todas las variables automáticas.  Se ubican en la pila del proceso.  Por ejemplo:
  
 <code> <code>
Línea 67: Línea 69:
 Acá //a// es un arreglo de 20 elementos que es creado al inicio de f y destruidos en el retorno de f.  Cuidado, una función no debe retornar la dirección de un arreglo local.  Aunque se puede y C lo permite, como su espacio es reutilizado en nuevas invocaciones de funciones, el resultado es impredecible y casi siempre erróneo. Acá //a// es un arreglo de 20 elementos que es creado al inicio de f y destruidos en el retorno de f.  Cuidado, una función no debe retornar la dirección de un arreglo local.  Aunque se puede y C lo permite, como su espacio es reutilizado en nuevas invocaciones de funciones, el resultado es impredecible y casi siempre erróneo.
  
-Observe aquí como se usa el arreglo en donde corresponde usar un puntero.  Esto es legal porque //a// representa la dirección de un entero y por lo tanto se puede asignar al parámetro p en ordenar.+Observe aquí como se usa el arreglo en donde corresponde usar un puntero.  Esto es legal porque //a// representa la dirección de un entero, es decir su tipo es //int*// y por lo tanto se puede asignar al parámetro p de la función ordenar.
  
 === Arreglos locales preinicializados === === Arreglos locales preinicializados ===
Línea 95: Línea 97:
 </code> </code>
  
-Compíle y ejecute con:+Compile y ejecute con:
  
   % gcc -m32 loop.c   % gcc -m32 loop.c
Línea 111: Línea 113:
 % gdb a.out % gdb a.out
 GNU gdb (Gentoo 7.3.1 p2) 7.3.1 GNU gdb (Gentoo 7.3.1 p2) 7.3.1
-Copyright (C) 2011 Free Software Foundation, Inc. +...
-License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> +
-This is free software: you are free to change and redistribute it. +
-There is NO WARRANTY, to the extent permitted by law.  Type "show copying" +
-and "show warranty" for details. +
-This GDB was configured as "x86_64-pc-linux-gnu"+
-For bug reporting instructions, please see: +
-<http://bugs.gentoo.org/>...+
 Reading symbols from /u/i/lmateu/Test/a.out...done. Reading symbols from /u/i/lmateu/Test/a.out...done.
 (gdb) b main (gdb) b main
Línea 151: Línea 146:
 </code> </code>
  
-Continúe así hasta que i tome el valor 10.  Luego observe lo que sucede cuando se ejecuta la instrucción ''a[i]0''.+Continúe así hasta que i tome el valor 10.  Ejecute una iteración más.  ¿Qué valor toma la variable i
 + 
 +==== Arreglos dinámicos ==== 
 + 
 +Son todos los arreglos que se crean llamando a malloc y se destruyen explícitamente con free, como se vió en el capítulo sobre punteros. Por lo tanto se ubican en el heap.  Su valor inicial es indeterminado y por lo tanto deben ser inicializados por el programador despúes de su creación. 
 + 
 +Observe que Java no posee arreglos globales ni locales a una función.  Todos los arreglos de Java son dinámicos.
arreglos.1344009310.txt.gz · Última modificación: 2012/08/03 15:55 por lmateu