Programación estructurada y modularidad
Flashcards
- ¿Qué utilidad aporta declarar el prototipo de una función antes de su uso?
- Permite que el compilador verifique los tipos de los argumentos y del retorno antes de que la función sea implementada o invocada en el código.
- ¿En qué situación resulta preferible utilizar una estructura switch frente a múltiples sentencias if encadenadas?
- Cuando se debe bifurcar la ejecución en función de múltiples valores específicos que puede tomar una misma variable discreta.
Preguntas tipo test
- ¿Qué instrucción permite saltar directamente a la siguiente iteración de un bucle?
- a) return
- b) continue
- c) break
- d) goto
Respuesta: b) continue. La instrucción continue interrumpe únicamente la iteración en curso y evalúa de nuevo la condición para la siguiente.
- ¿Qué ocurre con una variable declarada dentro de una función?
- a) Es accesible desde cualquier función
- b) Mantiene su valor globalmente
- c) Solo existe dentro de dicha función
- d) Pasa automáticamente por referencia
Respuesta: c) Solo existe dentro de dicha función. Las variables locales poseen ámbito restringido al bloque o función en que fueron definidas.
- ¿Cuál es la característica principal del bucle do...while frente a while?
- a) Se ejecuta al menos una vez
- b) Solo admite contadores enteros
- c) Itera siempre un número fijo
- d) No necesita condición lógica
Respuesta: a) Se ejecuta al menos una vez. Al verificar la condición al final del bloque, el cuerpo de do...while se ejecuta obligatoriamente un mínimo de una vez.
Tipos de datos: básicos, estructurados y tipos abstractos (TAD)
Flashcards
- ¿Qué ventaja operativa presenta una lista enlazada frente a un vector clásico?
- La lista enlazada puede crecer o decrecer de forma dinámica durante la ejecución sin requerir una dimensión fija previa.
- ¿Qué resultado arroja en C una comparación lógica si no se incluye stdbool.h?
- Devuelve un valor entero, interpretándose 0 como falso y cualquier valor numérico distinto de 0 como verdadero.
Preguntas tipo test
- ¿Qué política de extracción caracteriza a una estructura de tipo pila (stack)?
- a) Aleatoria
- b) Por prioridad numérica
- c) LIFO
- d) FIFO
Respuesta: c) LIFO. Las pilas responden al principio LIFO (Last In, First Out), donde el último elemento introducido es el primero en extraerse.
- ¿Cómo se accede a los diferentes elementos de un struct?
- a) Mediante un índice numérico
- b) A través de memoria contigua
- c) Con la función pop
- d) Por su nombre de campo
Respuesta: d) Por su nombre de campo. A diferencia de los vectores indexados numéricamente, los miembros de un registro se referencian por su identificador de campo.
- ¿Qué TAD resulta adecuado para gestionar trabajos en una impresora compartida?
- a) Cola (queue)
- b) Matriz bidimensional
- c) Pila (stack)
- d) Registro simple
Respuesta: a) Cola (queue). Las impresoras procesan documentos por orden de llegada, respondiendo al principio FIFO de una cola.
Punteros, recursividad y gestión de memoria dinámica en C
Flashcards
- ¿Por qué es imprescindible comprobar si el puntero devuelto por malloc es distinto de NULL?
- Porque si el sistema operativo no dispone de memoria suficiente, malloc devuelve NULL y desreferenciarlo causaría la caída del programa.
- ¿En qué zona de memoria residen las variables reservadas con malloc frente a las variables locales comunes?
- Las variables de malloc se ubican dinámicamente en el montículo (heap), mientras que las locales se gestionan automáticamente en la pila (stack).
Preguntas tipo test
- ¿Qué operador en C obtiene la dirección de memoria de una variable?
- a) Operador &
- b) Operador *
- c) Operador ->
- d) Operador %
Respuesta: a) Operador &. El operador & (dirección de) devuelve la posición física en memoria donde reside la variable indicada.
- ¿Qué función de stdlib.h asigna memoria inicializando sus bytes a cero?
- a) free
- b) malloc
- c) calloc
- d) realloc
Respuesta: c) calloc. A diferencia de malloc, calloc inicializa a cero todo el espacio de memoria reservado.
- ¿Qué fallo se origina al olvidar liberar memoria dinámica no utilizada?
- a) Error de sintaxis
- b) Stack overflow
- c) Puntero colgante
- d) Fuga de memoria (memory leak)
Respuesta: d) Fuga de memoria (memory leak). Omitir la liberación de memoria mediante free provoca un consumo acumulativo conocido como fuga de memoria.
Y 0 flashcards y 3 preguntas más en el documento.
Texto del documento
APUNTES FUNDAMENTOS DE PROGRAMACIÓN Grado en Ingeniería Informática Universidad Politécnica de Cataluña AprenAI 2026-2027 Repaso esencial de programación estructurada, tipos de datos y TADs, punteros, recursividad y gestión de memoria dinámica en lenguaje C para la UPC.
APREN.AI Índice 1 Programación estructurada y modularidad Principios de la programación estructurada y flujo de ejecución Estructuras condicionales e iterativas Modularidad: funciones, procedimientos y ámbito 2 Tipos de datos: básicos, estructurados y tipos abstractos (TAD) Tipos de datos básicos y conversión Estructuras homogéneas y heterogéneas Tipos Abstractos de Datos (TAD): pilas, colas y listas 3 Punteros, recursividad y gestión de memoria dinámica en C Concepto de puntero y operadores fundamentales Recursividad y marcos de pila Gestión de memoria dinámica y compilación en C 4 Resumen para repasar Programación estructurada y modularidad Tipos de datos y TADs Punteros, recursividad y memoria dinámica Soluciones de las preguntas de repaso Estos apuntes pueden contener errores u omisiones.
Son un material de apoyo y no sustituyen al temario oficial ni al profesorado: contrasta la información importante. Fundamentos de Programación: C, TADs y Memoria 1 1 Programación estructurada y modularidad AL ACABAR SABRÁS Diferenciar las estructuras de control condicionales e iterativas según el flujo requerido Diseñar subprogramas identificando el ámbito de variables y el mecanismo adecuado de paso de parámetros PIÉNSALO ANTES DE LEER 1 ¿Por qué los lenguajes modernos evitan sentencias de salto incondicional como goto?
Principios de la programación estructurada y flujo de ejecución La programación estructurada organiza el código mediante tres mecanismos de control fundamentales: secuencia, selección e iteración. Este paradigma prescinde de saltos arbitrarios como la sentencia goto , lo que incrementa notablemente la legibilidad, facilita el mantenimiento técnico y permite verificar formalmente los algoritmos. El flujo de un programa determina el orden temporal exacto en el que el procesador ejecuta las instrucciones. De forma predeterminada, dicho avance es puramente secuencial: cada sentencia se procesa tras la anterior siguiendo el orden textual del código fuente.
Para modificar esta secuencia básica, se emplean estructuras de control condicionales o iterativas que evalúan expresiones lógicas. En una etapa previa a la codificación formal, la lógica del flujo suele planificarse mediante pseudocódigo o diagramas de flujo independientes del lenguaje elegido. Todo programa informático responde al esquema clásico de tratamiento: recepción de datos de entrada, procesamiento algorítmico y emisión de resultados de salida. DEFINICIÓN Un algoritmo estructurado es una secuencia finita, ordenada y no ambigua de pasos que transforma las entradas recibidas en las salidas deseadas usando exclusivamente secuencias, alternativas y repeticiones.
Estructuras condicionales e iterativas Las bifurcaciones lógicas permiten desviar el camino de ejecución según el cumplimiento de predicados concretos: if : ejecuta un conjunto de instrucciones únicamente si la condición asociada resulta ser verdadera. if / else : establece un camino alternativo cuando la evaluación del predicado resulta falsa. else if encadenados: evalúan de forma secuencial múltiples condiciones excluyentes. switch / case : realiza una selección múltiple evaluando una expresión sobre valores discretos, ofreciendo gran claridad frente a múltiples comprobaciones sobre una única variable.
Fundamentos de Programación: C, TADs y Memoria 2 Por otro lado, los bucles o estructuras iterativas repiten la ejecución de un bloque mientras se mantenga cierta condición: while : verifica el predicado lógico antes de entrar en cada ciclo de iteración. do ... while : comprueba la condición después de ejecutar el cuerpo del bucle, asegurando al menos una iteración completa. for : diseñado para iteraciones bajo contador, sintetiza en su cabecera la inicialización, la condición de parada y el incremento o actualización de la variable de control. Control de salto en bucles: break finaliza inmediatamente el bucle; continue omite el resto del cuerpo actual y pasa a la siguiente iteración.
COMPRUEBA 2 ¿Qué diferencia operativa existe entre un bucle while y un bucle do...while? Modularidad: funciones, procedimientos y ámbito La modularidad consiste en fragmentar un problema complejo en subprogramas más pequeños y especializados, donde cada módulo asume una responsabilidad lógica bien delimitada. Esta técnica fomenta la reutilización, simplifica las pruebas y la depuración, y favorece el trabajo cooperativo. En lenguaje C existen dos variantes según devuelvan o no un resultado: Función: subprograma que calcula y entrega un valor de retorno, pudiendo invocarse dentro de cualquier expresión.
Acción o procedimiento: subprograma enfocado en realizar una tarea sin devolver ningún valor (se implementa mediante el tipo void ). El prototipo o cabecera establece la interfaz del subprograma declarando su nombre, tipos de parámetros y valor de retorno, informando al compilador con anterioridad a su invocación real. La comunicación de datos entre el programa y sus módulos se articula mediante dos mecanismos: Paso por valor: la función recibe una copia exacta del dato. Las modificaciones internas no afectan a la variable del entorno llamante.
Paso por referencia: se transfiere la dirección de memoria de la variable mediante punteros, permitiendo que la función modifique directamente el valor original. Respecto a la visibilidad, las variables locales solo existen dentro del bloque o función en el que se declaran, mientras que las variables globales resultan accesibles desde cualquier zona del código. ERROR FRECUENTE Olvidar pasar un parámetro por referencia cuando se pretende modificar su valor fuera del subprograma. En C, pasar una variable directamente siempre genera una copia local (paso por valor); cualquier cambio realizado sobre dicha copia se descarta al finalizar la función.
Fundamentos de Programación: C, TADs y Memoria 3 PROCESO Esquema básico del flujo de un programa 1 Entrada de datos Captura de información externa o parámetros iniciales 2 Proceso algorít mico Transformación de los datos mediante lógica estructurada 3 Salida de resulta dos Emisión o almacenamiento de la información procesada IDEAS CLAVE La programación estructurada descarta saltos incondicionales y articula el código en secuencia, selección e iteración. Los bucles while evalúan la condición al inicio, mientras que do...while garantiza al menos una ejecución. El paso por valor transfiere una copia del dato; el paso por referencia opera sobre la dirección de memoria original.
Las variables locales se limitan al ámbito de su bloque, a diferencia de las variables globales. COMPRUEBA LO QUE HAS APRENDIDO 3. ¿Qué utilidad aporta declarar el prototipo de una función antes de su uso? 4. ¿En qué situación resulta preferible utilizar una estructura switch frente a múltiples sentencias if encadenadas? Test Rodea la respuesta correcta. Las soluciones están al final. 5. ¿Qué instrucción permite saltar directamente a la siguiente iteración de un bucle? 6. ¿Qué ocurre con una variable declarada dentro de una función? 7. ¿Cuál es la característica principal del bucle do...while frente a while?
return a) continue b) break c) goto d) Es accesible desde cualquier función a) Mantiene su valor globalmente b) Solo existe dentro de dicha función c) Pasa automáticamente por referencia d) Se ejecuta al menos una vez a) Solo admite contadores enteros b) Itera siempre un número fijo c) No necesita condición lógica d) Fundamentos de Programación: C, TADs y Memoria 4 8. ¿Cómo se consigue en lenguaje C que una función modifique la variable original?
2 Tipos de datos: básicos, estructurados y tipos abstractos (TAD) AL ACABAR SABRÁS Seleccionar la estructura de datos adecuada para modelar problemas homogéneos o heterogéneos Diferenciar el comportamiento y aplicaciones de pilas, colas y listas enlazadas PIÉNSALO ANTES DE LEER 9 ¿Por qué un programa separa la interfaz de un TAD de su código de implementación? Tipos de datos básicos y conversión Un tipo de dato determina el conjunto admisible de valores que puede adoptar una variable, así como las operaciones válidas aplicables sobre ella. Se clasifican fundamentalmente en tipos simples (un único valor escalar) y tipos estructurados (agrupaciones de múltiples valores).
Tipo en C Naturaleza del dato Detalles de representación int Entero Valores numéricos sin parte fraccionaria. float , double Reales (coma flotante) Números con parte decimal; double aporta mayor precisión. char Carácter Símbolo alfanumérico representado por código entero (como ASCII). Booleano Lógico (verdadero / falso) Simulado clásicamente con enteros (0 es falso; distinto de 0 es verdadero); soporte nativo mediante <stdbool.h> a partir del estándar C99. El rango numérico y la ocupación en bytes de cada tipo dependen directamente de la arquitectura de la máquina y del compilador empleado.
Para transformar de forma explícita un dato entre tipos distintos se utiliza la conversión de tipos (cast), necesaria, por ejemplo, para forzar divisiones en coma flotante entre operandos enteros: (float) numerador / denominador . Usando paso por valor a) Pasando su dirección mediante punteros b) Incluyendo la directiva break c) Declarando la función como void d) Fundamentos de Programación: C, TADs y Memoria 5 Estructuras homogéneas y heterogéneas Los datos pueden estructurarse en memoria contigua o asociativa: Vector (array unidimensional): colección lineal de elementos del mismo tipo almacenados de forma contigua en memoria.
Cada posición se indexa numéricamente comenzando siempre en el índice 0 en C. Matriz (array bidimensional): tabla organizada por filas y columnas accesible mediante dos índices: [fila][columna] . Se procesa típicamente mediante bucles for anidados. Tupla o registro ( struct ): agrupación heterogénea de datos bajo un mismo identificador, en la que cada componente se referencia por un nombre de campo concreto. Tabla: colección de registros organizados bajo un índice numérico; habitualmente se implementa como un array de estructuras ( struct ).
PARA RECORDARLO En lenguaje C, al suministrar un vector como argumento de una función, este no se duplica por valor: decae automáticamente a un puntero que referencia su primer elemento. COMPRUEBA 10 ¿En qué se diferencian fundamentalmente un vector y un struct? Tipos Abstractos de Datos (TAD): pilas, colas y listas Un Tipo Abstracto de Datos (TAD) define una estructura de datos exclusivamente a partir del comportamiento de las operaciones que componen su interfaz pública, abstrayéndose por completo de los detalles internos de implementación. Esta separación neta entre el «qué hace» y el «cómo lo hace» es el pilar de la encapsulación.
TAD Disciplina de acceso Operaciones principales Casos de aplicación Pila (stack) LIFO (Last In, First Out): el último en entrar es el primero en salir. push (apilar), pop (desapilar), top/peek (cima), isEmpty . Evaluación de expresiones, función de deshacer (undo), pila de llamadas a funciones. Cola (queue) FIFO (First In, First Out): el primero en entrar es el primero en salir. enqueue (encolar), dequeue (desencolar), front (frente), isEmpty . Colas de impresión de documentos, gestión de tareas en sistemas operativos, colas de espera. Lista enlazada Secuencia encadenada de nodos (dato y puntero al siguiente nodo). Insertar, eliminar, buscar y recorrer.
Estructuras de tamaño dinámico en tiempo de ejecución (variantes simple, doble y circular). Tanto las pilas como las colas pueden implementarse sobre vectores estáticos (asumiendo un límite de capacidad fijo) o mediante listas enlazadas dinámicas, lo que evita restricciones de memoria predefinidas. Fundamentos de Programación: C, TADs y Memoria 6 ERROR FRECUENTE Confundir las disciplinas LIFO y FIFO al implementar algoritmos de procesamiento secuencial. Utilizar una cola (FIFO) para gestionar llamadas recursivas o retrocesos destruye el orden de retorno inverso que exige una pila (LIFO).
ESQUEMA Clasificación de tipos de datos IDEAS CLAVE Los tipos simples contienen valores escalares individuales; los estructurados agrupan múltiples datos. Los arrays son colecciones homogéneas continuas; los structs permiten agrupar campos de tipos dispares. Un TAD independiza la interfaz de operaciones de la representación interna en memoria. Una pila sigue la disciplina LIFO y una cola se rige por el principio FIFO. COMPRUEBA LO QUE HAS APRENDIDO 11. ¿Qué ventaja operativa presenta una lista enlazada frente a un vector clásico? 12. ¿Qué resultado arroja en C una comparación lógica si no se incluye stdbool.h? Test Rodea la respuesta correcta. Las soluciones están al final. 13.
¿Qué política de extracción caracteriza a una estructura de tipo pila (stack)? Tipos de datos Conjunto de valores y operaciones Tipos básicos Valores escalares individuales int, float, char Enteros, reales y caracteres Tipos estructurados Agrupaciones de datos Homogéneos Vectores y matrices Heterogéneos Tuplas o registros struct Aleatoria a) Por prioridad numérica b) LIFO c) FIFO d) Fundamentos de Programación: C, TADs y Memoria 7 14. ¿Cómo se accede a los diferentes elementos de un struct? 15. ¿Qué TAD resulta adecuado para gestionar trabajos en una impresora compartida? 16. ¿Qué ocurre internamente al pasar un vector como argumento en C?
3 Punteros, recursividad y gestión de memoria dinámica en C AL ACABAR SABRÁS Manipular direcciones de memoria mediante punteros y sus operadores asociados Diseñar algoritmos recursivos garantizando la convergencia hacia el caso base Gestionar el ciclo de vida de la memoria dinámica en el heap mediante malloc y free PIÉNSALO ANTES DE LEER 17 ¿Cómo puede un programa almacenar una lista de elementos cuyo número exacto no se conoce antes de iniciarlo? Concepto de puntero y operadores fundamentales Un puntero es una variable cuyo contenido es la dirección física de memoria de otra variable. En lugar de albergar un dato elemental directamente, almacena la ubicación en la que dicho valor reside.
En lenguaje C, el manejo de punteros se sustenta en dos operadores clave: Operador de dirección ( & ): obtiene la dirección de memoria asignada a una variable (por ejemplo, p = &x; ). Operador de indirección o desreferencia ( * ): accede al valor almacenado en la posición de memoria a la que apunta la variable puntero (por ejemplo, *p = 20; ). Los punteros guardan una equivalencia directa con los vectores: el identificador de un vector representa la dirección de su primer elemento. De este modo, es posible desplazarse entre posiciones mediante aritmética de punteros (la expresión *(v + 1) equivale exactamente a v[1] ).
Un puntero puede tomar el valor especial NULL , denotando que no referencia ninguna dirección válida del sistema. Mediante un índice numérico a) A través de memoria contigua b) Con la función pop c) Por su nombre de campo d) Cola (queue) a) Matriz bidimensional b) Pila (stack) c) Registro simple d) Se copia el array completo a) Se convierte en lista enlazada b) Decae a un puntero c) Se genera un error sintáctico d) Fundamentos de Programación: C, TADs y Memoria 8 ERROR FRECUENTE Desreferenciar un puntero que contiene NULL o acceder a un puntero colgante (que apunta a memoria previamente liberada mediante free ).
Ambas acciones desencadenan fallos graves en tiempo de ejecución, habitualmente manifestados como violaciones de segmento (segmentation fault). Recursividad y marcos de pila Un subprograma recursivo es aquel que, en el interior de su propia definición, realiza llamadas dirigidas a sí mismo con el propósito de resolver una versión de menor tamaño del problema original. Para funcionar correctamente, todo diseño recursivo debe contemplar dos elementos: A nivel de ejecución, cada invocación genera un marco de pila (stack frame) que almacena los parámetros, las variables locales y el punto de retorno de la llamada. Estos marcos se apilan sucesivamente y se desapilan al resolver los casos base.
Cualquier proceso recursivo puede formularse de forma iterativa y viceversa; no obstante, si el caso base resulta inalcanzable, la acumulación descontrolada provoca un desbordamiento de pila (stack overflow). COMPRUEBA 18 ¿Qué consecuencia inmediata tiene omitir el caso base en una función recursiva? Gestión de memoria dinámica y compilación en C La memoria dinámica es el espacio de memoria que el programa reserva y libera explícitamente durante su ejecución en el montículo o heap. Se distingue de la memoria estática y automática (alojada en la pila o stack), cuyas dimensiones quedan fijadas de antemano durante la compilación.
Resulta imprescindible cuando el tamaño de los datos es variable o se desconoce antes de ejecutar el programa. Las funciones estándar provistas por la cabecera <stdlib.h> son: malloc(tam) : reserva un bloque continuo de memoria en bytes sin inicializar y retorna un puntero a su inicio (o NULL si la asignación falla). calloc(n, tam) : reserva memoria para n elementos inicializando todos sus bytes a cero. realloc(ptr, nuevo_tam) : redimensiona un bloque de memoria previamente concedido. free(ptr) : libera el bloque de memoria referenciado, devolviéndolo al sistema para su reutilización.
Omitir la llamada a free origina fugas de memoria (memory leaks), mientras que liberar dos veces el mismo bloque genera un error crítico (double free). Caso base: condición elemental que se resuelve de manera directa sin efectuar nuevas llamadas recursivas, asegurando el cese del algoritmo. 1 Caso recursivo: invocación de la función sobre un subproblema reducido que converge progresivamente hacia el caso base. 2 Fundamentos de Programación: C, TADs y Memoria 9 Por último, un programa en C parte de la función main() como punto de entrada.
Para generar el ejecutable, el código fuente atraviesa tres etapas sucesivas: PROCESO Fases de construcción de un programa en C Las bibliotecas del sistema como <stdio.h> gestionan la comunicación con el usuario mediante printf y scanf , mientras que <stdlib.h> provee los mecanismos de control dinámico del montículo. IDEAS CLAVE Un puntero almacena direcciones de memoria y se desreferencia con el operador *. La recursividad requiere un caso base terminal para evitar el desbordamiento de pila. malloc y calloc reservan memoria en el montículo (heap), que debe liberarse obligatoriamente con free. El proceso de compilación en C consta de preprocesador, compilador y enlazador (linker).
COMPRUEBA LO QUE HAS APRENDIDO 19. ¿Por qué es imprescindible comprobar si el puntero devuelto por malloc es distinto de NULL? 20. ¿En qué zona de memoria residen las variables reservadas con malloc frente a las variables locales comunes? Código fuente (.c) Texto con directivas e instrucciones C 1 Preprocesador Procesa directivas como include y define 2 Compilador Genera el código objeto intermedio 3 Enlazador (linker) Combina código objeto con bibliotecas externas 4 Ejecutable final Binario listo para ejecución en máquina 5 Fundamentos de Programación: C, TADs y Memoria 10 Test Rodea la respuesta correcta. Las soluciones están al final. 21.
¿Qué operador en C obtiene la dirección de memoria de una variable? 22. ¿Qué función de stdlib.h asigna memoria inicializando sus bytes a cero? 23. ¿Qué fallo se origina al olvidar liberar memoria dinámica no utilizada? 24. ¿Qué componente del proceso de compilación combina el código objeto con las bibliotecas? 4 Resumen para repasar Programación estructurada y modularidad Concepto Definición Programación estructurada Paradigma que articula el flujo de control exclusivamente mediante secuencia, selección (condicionales) e iteración (bucles), prescindiendo de saltos incondicionales.
Bucle while frente a do...while El bucle while evalúa la condición de parada antes de iterar, mientras que do...while la evalúa al final, ejecutándose siempre al menos una vez. Paso por valor Paso de parámetros donde el subprograma recibe una copia independiente del dato, sin alterar la variable original llamante. Paso por referencia Paso en el que se transfiere la dirección de memoria de la variable mediante punteros, permitiendo modificar su valor original. Ámbito (scope) Espacio de visibilidad de las variables: local si solo existen dentro de su función o bloque, y global si son accesibles en todo el programa.
Operador & a) Operador * b) Operador -> c) Operador % d) free a) malloc b) calloc c) realloc d) Error de sintaxis a) Stack overflow b) Puntero colgante c) Fuga de memoria (memory leak) d) Depurador a) Compilador b) Enlazador (linker) c) Preprocesador d) Fundamentos de Programación: C, TADs y Memoria 11 Tipos de datos y TADs Concepto Definición Vector (array) Colección homogénea de elementos contiguos en memoria indexados a partir de 0 que decae a un puntero al pasarse a una función. Registro (struct) Tipo estructurado heterogéneo que agrupa campos de diferentes tipos identificados por un nombre.
Tipo Abstracto de Datos (TAD) Modelo de datos definido por su interfaz de operaciones públicas, ocultando completamente los detalles de su implementación física. Pila (stack) Estructura con política LIFO (último en entrar, primero en salir) utilizada en llamadas a funciones y desapilado de operaciones. Cola (queue) Estructura con política FIFO (primero en entrar, primero en salir) empleada en colas de impresión y planificación de tareas. Lista enlazada Secuencia dinámica de nodos enlazados mediante punteros cuyo tamaño varía libremente en tiempo de ejecución.
Punteros, recursividad y memoria dinámica Concepto Definición Puntero Variable que almacena la dirección de memoria de otra variable, manejada con los operadores de dirección (&) y desreferencia (*). Caso base recursivo Condición de parada elemental en una función recursiva que se resuelve directamente e impide el desbordamiento de pila (stack overflow). Memoria dinámica (heap) Zona de memoria gestionada explícitamente en ejecución mediante malloc, calloc, realloc y liberada obligatoriamente con free. Fuga de memoria (memory leak) Pérdida de memoria no recuperable originada al omitir la liberación con free de bloques reservados dinámicamente.
Proceso de compilación Secuencia que transforma el código fuente en ejecutable mediante las etapas de preprocesador, compilador y enlazador (linker). Fundamentos de Programación: C, TADs y Memoria 12 Soluciones de las preguntas de repaso 1. Porque rompen la secuencia predecible del flujo de control, dificultando el seguimiento, depuración y verificación del software. 2. El bucle while comprueba la condición antes de ejecutar las instrucciones (puede ejecutarse cero veces), mientras que do...while la evalúa al final, garantizando que el bloque se procese siempre al menos una vez. 3.
Permite que el compilador verifique los tipos de los argumentos y del retorno antes de que la función sea implementada o invocada en el código. 4. Cuando se debe bifurcar la ejecución en función de múltiples valores específicos que puede tomar una misma variable discreta. 5. b) continue. La instrucción continue interrumpe únicamente la iteración en curso y evalúa de nuevo la condición para la siguiente. 6. c) Solo existe dentro de dicha función. Las variables locales poseen ámbito restringido al bloque o función en que fueron definidas. 7. a) Se ejecuta al menos una vez. Al verificar la condición al final del bloque, el cuerpo de do...while se ejecuta obligatoriamente un mínimo de una vez. 8.
b) Pasando su dirección mediante punteros. El paso por referencia en C se emula enviando la dirección de memoria del dato a través de punteros. 9. Para permitir modificar la lógica interna sin alterar el resto de componentes que utilizan dicha estructura. 10. Un vector almacena elementos homogéneos (del mismo tipo) indexados numéricamente, mientras que un struct agrupa elementos heterogéneos (de tipos distintos) identificados por nombres de campo. 11. La lista enlazada puede crecer o decrecer de forma dinámica durante la ejecución sin requerir una dimensión fija previa. 12. Devuelve un valor entero, interpretándose 0 como falso y cualquier valor numérico distinto de 0 como verdadero. 13.
c) LIFO. Las pilas responden al principio LIFO (Last In, First Out), donde el último elemento introducido es el primero en extraerse. 14. d) Por su nombre de campo. A diferencia de los vectores indexados numéricamente, los miembros de un registro se referencian por su identificador de campo. 15. a) Cola (queue). Las impresoras procesan documentos por orden de llegada, respondiendo al principio FIFO de una cola. 16. c) Decae a un puntero. En C los vectores decaen automáticamente a la dirección de memoria de su elemento inicial. 17. Mediante reserva de memoria dinámica en el montículo (heap), solicitando memoria conforme se requiera durante la ejecución. 18.
La función genera llamadas recursivas infinitas hasta saturar el espacio de memoria asignado a la pila de ejecución, produciendo un desbordamiento de pila (stack overflow). 19. Porque si el sistema operativo no dispone de memoria suficiente, malloc devuelve NULL y desreferenciarlo causaría la caída del programa. Fundamentos de Programación: C, TADs y Memoria 13 20. Las variables de malloc se ubican dinámicamente en el montículo (heap), mientras que las locales se gestionan automáticamente en la pila (stack). 21. a) Operador &. El operador & (dirección de) devuelve la posición física en memoria donde reside la variable indicada. 22. c) calloc.
A diferencia de malloc, calloc inicializa a cero todo el espacio de memoria reservado. 23. d) Fuga de memoria (memory leak). Omitir la liberación de memoria mediante free provoca un consumo acumulativo conocido como fuga de memoria. 24. c) Enlazador (linker). El enlazador o linker une los ficheros objeto y las bibliotecas para construir el archivo ejecutable final. Fundamentos de Programación: C, TADs y Memoria 14