estructuras
Diferencias
Muestra las diferencias entre dos versiones de la página.
Próxima revisión | Revisión previa | ||
estructuras [2012/08/23 02:12] – creado lmateu | estructuras [2015/09/30 20:03] (actual) – [Estructuras recursivas] lmateu | ||
---|---|---|---|
Línea 88: | Línea 88: | ||
(*u).x ≡ u->x | (*u).x ≡ u->x | ||
| | ||
- | Y por lo tanto podemos reescribir la función | + | Y por lo tanto podemos reescribir la función |
< | < | ||
Línea 134: | Línea 134: | ||
struct punto *nuevoPunto(float x, float y) { | struct punto *nuevoPunto(float x, float y) { | ||
/* se pide espacio para un punto en el heap */ | /* se pide espacio para un punto en el heap */ | ||
- | struct punto *pa= (struct punto*)malloc(sizeof(struct punto)); | + | struct punto *pa= malloc(sizeof(struct punto)); |
pa->x= x; | pa->x= x; | ||
pa->y= y; | pa->y= y; | ||
Línea 152: | Línea 152: | ||
==== Typedef ==== | ==== Typedef ==== | ||
- | Escribir siempre struct punto en cada declaración resulta pesado sintácticamente. | + | Escribir siempre |
< | < | ||
Línea 158: | Línea 158: | ||
</ | </ | ||
- | Esto intruduce 2 nuevos tipos: ENTERO y PUNTERO. | + | Esto intruduce 2 nuevos tipos: |
< | < | ||
Línea 171: | Línea 171: | ||
</ | </ | ||
- | Es como haber eliminado el typedef y substituido ENTERO por x y PUNTERO por p. | + | Es como haber eliminado el //typedef// y substituido |
¿A qué sería equivamente escribir lo siguiente? | ¿A qué sería equivamente escribir lo siguiente? | ||
Línea 179: | Línea 179: | ||
</ | </ | ||
- | De la misma forma se pueden declarar el tipo Punto: | + | De la misma forma se pueden declarar el tipo //Punto//: |
< | < | ||
Línea 196: | Línea 196: | ||
</ | </ | ||
+ | Observe que la etiqueta que viene después de //struct// es opcional. | ||
+ | También se pudo haber colocado explícitamente la etiqueta //punto//: | ||
+ | |||
+ | < | ||
+ | typedef struct punto { | ||
+ | float x, y; | ||
+ | } Punto; | ||
+ | </ | ||
+ | |||
+ | //La etiqueta del struct se puede omitir cuando no se va a usar a continuación en el archivo.// | ||
==== Estructuras recursivas ==== | ==== Estructuras recursivas ==== | ||
Línea 213: | Línea 223: | ||
</ | </ | ||
- | La declaración de Node también se puede escribir como: | + | La declaración de //Node// también se puede escribir como: |
< | < | ||
Línea 222: | Línea 232: | ||
</ | </ | ||
- | Pero esto genera | + | Observe que en este caso la etiqueta //node// sí se debe especificar porque se usa dentro de //Nodo//. |
+ | No se puede usar //Node// directamente como en el ejemplo de más abajo porque se generaría | ||
< | < | ||
Línea 231: | Línea 242: | ||
</ | </ | ||
- | El problema es que el tipo Node es desconocido en el momento de declarar el campo next. Recuerde que en C, el alcance de un identificador comienza en el punto de programa en donde se definió. | + | El problema es que el tipo Node es desconocido en el momento de declarar el campo next. Recuerde que en C, el alcance de un identificador comienza en el punto del programa en donde se definió. |
=== Ejemplo: recorrer una lista enlazada === | === Ejemplo: recorrer una lista enlazada === | ||
Línea 247: | Línea 258: | ||
=== Ejemplo: inserción === | === Ejemplo: inserción === | ||
- | Supongamos que la lista enlazada posee una cabeza | + | La inserción |
< | < | ||
void insertar(Node **ppnode, int y) { | void insertar(Node **ppnode, int y) { | ||
- | Node *ins; | + | Node *pnode= *ppnode; |
- | while (*ppnode!=NULL && | + | while (pnode != NULL && |
- | ppnode= &(*pnode)-> | + | ppnode= & pnode-> |
- | + | pnode= *ppnode; | |
- | | + | |
+ | | ||
+ | Node *ins= malloc(sizeof(Node)); | ||
ins->x= y; | ins->x= y; | ||
- | ins-> | + | ins-> |
*ppnode= ins; | *ppnode= ins; | ||
} | } | ||
</ | </ | ||
+ | Observe que insertar recibe un puntero al puntero que referencia el primer nodo de la lista. | ||
Pruebe esta función con este código: | Pruebe esta función con este código: | ||
Línea 278: | Línea 292: | ||
Haga un diagrama de variables y punteros para ver como se inserta el 3. | Haga un diagrama de variables y punteros para ver como se inserta el 3. | ||
- | === Ejercicio === | + | === Ejercicio |
Suponga que la lista enlazada tiene una cabeza de mentira como en el ejercicio anterior. | Suponga que la lista enlazada tiene una cabeza de mentira como en el ejercicio anterior. | ||
+ | === Ejercicio 2 === | ||
+ | |||
+ | Resuelva la parte b de la pregunta 2 del [[http:// | ||
==== Enum ==== | ==== Enum ==== | ||
Línea 299: | Línea 316: | ||
Los identificadores INT y FLOAT son constantes y por lo tanto no pueden aparecer al lado izquierdo de una asignación. | Los identificadores INT y FLOAT son constantes y por lo tanto no pueden aparecer al lado izquierdo de una asignación. | ||
+ | |||
+ | Alternativamente se puede usar typedef para poder usar el tipo Tag en vez de enum tag que es muy largo: | ||
+ | |||
+ | < | ||
+ | #include < | ||
+ | |||
+ | typedef enum { INT, FLOAT } Tag; | ||
+ | |||
+ | int main() { | ||
+ | Tag a= INT; | ||
+ | Tag b= FLOAT; | ||
+ | printf(" | ||
+ | } | ||
+ | </ | ||
Para hacer que las etiquetas comiencen de 1: | Para hacer que las etiquetas comiencen de 1: | ||
Línea 386: | Línea 417: | ||
Para poder deducir la respuesta primero hay que enunciar un requerimiento de hardware: los microprocesadores | Para poder deducir la respuesta primero hay que enunciar un requerimiento de hardware: los microprocesadores | ||
modernos leen y escriben más eficientemente variables de tipos primitivos cuando ellas están // | modernos leen y escriben más eficientemente variables de tipos primitivos cuando ellas están // | ||
- | Una variabble | + | Una variable |
su tamaño. | su tamaño. | ||
punto flotante de doble precisión (double) debe ser múltiplo de 8. Por esta razón los compiladores de | punto flotante de doble precisión (double) debe ser múltiplo de 8. Por esta razón los compiladores de | ||
Línea 411: | Línea 442: | ||
</ | </ | ||
- | ¿Cómo se puede garantizar que n esté alineado? | + | ¿Cómo se puede garantizar que //n// esté alineado? |
estructura sin saber su tipo. Conoce el tamaño la región pedida, pero no sabe si es para un arreglo de 8 caracteres, | estructura sin saber su tipo. Conoce el tamaño la región pedida, pero no sabe si es para un arreglo de 8 caracteres, | ||
- | para el cual no hay requerimiento de alineamiento, | + | para el cual no hay requerimiento de alineamiento, |
- | se pone en el peor caso: 8. Malloc siempre retorna direcciones múltiplo de 8. | + | se pone en el peor caso: 8. |
- | Pero aún así si el compilador asigna un desplazamiento 0 para c y un desplazamiento 1 para n, la variable n | + | Pero aún así si el compilador asigna un desplazamiento 0 para //c// y un desplazamiento 1 para //n//, |
- | estaría desalineada. | + | la variable |
- | ocupar los bytes 1, 2 y 3 de la estructura. | + | La solución está en que el compilador asigna un desplazamiento 4 para //n// y deja sin |
+ | ocupar los bytes 1, 2 y 3 de la estructura. | ||
El compilador sacrifica un poco de memoria para ganar eficiencia en tiempo de ejecución. | El compilador sacrifica un poco de memoria para ganar eficiencia en tiempo de ejecución. | ||
una variable no está alineada, el procesador requiere más ciclos del reloj para leerla o modificarla. | una variable no está alineada, el procesador requiere más ciclos del reloj para leerla o modificarla. | ||
Línea 424: | Línea 456: | ||
//bus error// y el programa no continúa. | //bus error// y el programa no continúa. | ||
- | Para responder cual es el tamaño de '' | + | Para responder cual es el tamaño de //sizeof struct T// consideremos este código: |
< | < |
estructuras.1345687962.txt.gz · Última modificación: 2012/08/23 02:12 por lmateu