## Bloque 3 Tema 2. Lenguajes de programación. Representación de tipos de datos. Operadores. Instrucciones condicionales. Bucles y recursividad. Procedimientos, funciones y parámetros. Vectores y registros. Estructura de un programa.

Este tema estudia los fundamentos de los lenguajes de programación, los elementos básicos de un programa y las estructuras de control.

---

## 1. Lenguajes de programación

Un lenguaje de programación es un lenguaje formal que especifica instrucciones para que un ordenador realice determinadas tareas. Se compone de sintaxis, que son las reglas que definen la forma correcta de escribir las instrucciones; semántica, que es el significado de cada instrucción; y pragmática, que es el uso práctico del lenguaje.

Por nivel de abstracción los lenguajes se clasifican en tres grupos. Los lenguajes de bajo nivel son cercanos al hardware y comprensibles directamente por la máquina; incluyen el lenguaje máquina en binario y el ensamblador, que usa nemónicos como MOV, ADD o JMP. Los lenguajes de nivel medio, como C, combinan el control del hardware con abstracciones. Los lenguajes de alto nivel, como Python, Java o Pascal, son independientes del hardware y cercanos al lenguaje humano.

Por paradigma los lenguajes se clasifican en imperativo o procedural, que usa secuencias de instrucciones como C o Pascal; orientado a objetos, que modela la realidad con objetos como Java o C++; funcional, basado en funciones matemáticas como Haskell; lógico o declarativo como Prolog o SQL; orientado a eventos como JavaScript; y multiparadigma como Python.

Por mecanismo de ejecución se distinguen los lenguajes compilados, como C, que traducen todo el código antes de ejecutar; los interpretados, como Python, que ejecutan línea a línea; y los de bytecode o máquina virtual, como Java con su JVM o C# con el CLR de .NET, que compilan a código intermedio portable.

Las fases del compilador son análisis léxico, análisis sintáctico, análisis semántico, generación de código intermedio, optimización y generación de código final.

---

## 2. Tipos de datos

Un tipo de dato define el conjunto de valores posibles que puede tomar una variable, las operaciones permitidas sobre ella y su representación en memoria.

Los tipos de datos simples o primitivos son los siguientes. Los enteros representan números sin parte decimal; el tipo byte ocupa 1 byte, el short 2 bytes, el int 4 bytes y el long 8 bytes; se almacenan en complemento a dos para los negativos. Los reales o coma flotante siguen el estándar IEEE 754; float ocupa 4 bytes con 7 dígitos de precisión y double ocupa 8 bytes con 15 dígitos. Los caracteres representan un único símbolo y usan codificaciones ASCII para 128 o 256 caracteres y Unicode o UTF-8 para más de un millón. El booleano solo admite verdadero o falso y ocupa 1 byte. Los enumerados definen un conjunto finito de valores con nombre.

Los tipos de datos compuestos incluyen vectores o arrays, que son colecciones de elementos del mismo tipo accesibles por índice; registros o structs, que agrupan campos de distintos tipos bajo un mismo nombre; cadenas de texto o String; y clases u objetos en programación orientada a objetos.

Las variables son posiciones en memoria cuyo valor puede cambiar durante la ejecución. Las constantes no pueden modificarse tras su inicialización. El ámbito de una variable puede ser local, global o estático. La conversión implícita o widening es automática y sin pérdida de información; la conversión explícita o narrowing requiere indicarse manualmente y puede perder información.

---

## 3. Operadores

Los operadores aritméticos son suma, resta, multiplicación, división, módulo o resto y potencia. En la división entera el resultado es entero: 7 dividido entre 2 es 3.

Los operadores relacionales comparan dos valores y devuelven un booleano: igual, distinto, menor, mayor, menor o igual y mayor o igual.

Los operadores lógicos son AND, que es verdadero si ambos operandos son verdaderos; OR, que es verdadero si al menos uno lo es; y NOT, que invierte el valor. Utilizan evaluación en cortocircuito.

Los operadores de asignación son la asignación simple y las versiones compuestas como más igual, menos igual, por igual, entre igual y módulo igual.

Los operadores de bits operan sobre los bits individuales: AND bit a bit, OR bit a bit, XOR, complemento, y desplazamientos a izquierda y derecha.

El operador ternario es una versión compacta del if-else para asignaciones simples.

La precedencia de operadores de mayor a menor es paréntesis, operadores unarios, multiplicativos, aditivos, desplazamientos, relacionales, igualdad, bitwise, lógicos, ternario y finalmente asignación.

---

## 4. Instrucciones condicionales

Las instrucciones condicionales permiten tomar decisiones en función del valor de una condición booleana.

La estructura if, else if y else ejecuta distintos bloques según las condiciones evaluadas de forma encadenada. Solo se ejecuta uno de los bloques.

La estructura switch-case compara una variable contra múltiples valores constantes. La instrucción break es esencial para evitar la ejecución en cascada o fall-through de casos siguientes. El caso default equivale al else y se ejecuta si ningún caso coincide.

---

## 5. Bucles y recursividad

Los bucles permiten ejecutar un bloque de código repetidamente.

El bucle while evalúa la condición antes de cada iteración; si es falsa desde el inicio, el cuerpo no se ejecuta.

El bucle do-while evalúa la condición al final, de modo que el cuerpo se ejecuta siempre al menos una vez.

El bucle for es ideal cuando se conoce el número de iteraciones de antemano; tiene tres partes: inicialización, condición y actualización. El for-each recorre automáticamente todos los elementos de una colección.

Las instrucciones break, continue y return controlan la ejecución dentro del bucle.

La recursividad consiste en que una función se llama a sí misma para resolver un problema. Toda función recursiva necesita un caso base que detenga la recursión y una llamada recursiva que se acerque al caso base. Cada llamada añade un marco de activación a la pila de llamadas; si hay demasiadas llamadas anidadas se produce un desbordamiento de pila o StackOverflowError. Los ejemplos clásicos son el factorial, la serie de Fibonacci y las torres de Hanói. La recursividad de cola permite que el compilador la optimice como iteración.

---

## 6. Procedimientos, funciones y parámetros

Un subprograma o subrutina es un bloque de código con nombre que realiza una tarea concreta y puede ser llamado desde distintos puntos del programa. Sus ventajas son la reutilización de código, la modularidad, la abstracción y la facilidad de pruebas.

La diferencia entre procedimiento y función es que el procedimiento no devuelve valor, o devuelve void, mientras que la función devuelve un valor y puede usarse dentro de expresiones.

Los parámetros formales son las variables declaradas en la firma de la función. Los argumentos son los valores concretos que se pasan al llamarla.

El paso por valor copia el valor del argumento; los cambios dentro de la función no afectan a la variable original. El paso por referencia pasa la dirección de memoria del argumento; los cambios sí afectan al original.

---

## 7. Vectores y registros

Un vector o array es una estructura de datos que almacena un conjunto de elementos del mismo tipo en posiciones contiguas de memoria, accesibles mediante un índice que comienza en cero. Los arrays multidimensionales o matrices almacenan datos en filas y columnas.

Un registro o struct es una estructura que agrupa campos de distintos tipos bajo un mismo nombre. En programación orientada a objetos los registros se representan como clases cuyos campos son atributos del objeto.

---

## 8. Estructura de un programa

La estructura típica de un programa incluye la sección de declaraciones o importaciones de módulos externos, la declaración de constantes y variables globales, la definición de procedimientos y funciones, y el programa principal donde comienza la ejecución.

---

## Miniresumen final del tema

Los lenguajes de programación se clasifican por nivel de abstracción, paradigma y mecanismo de ejecución. Los tipos de datos primitivos son enteros, reales, char y booleanos; los compuestos incluyen vectores y registros. Los operadores aritméticos, relacionales, lógicos y de bits permiten operar sobre los datos. Las instrucciones if-else y switch controlan el flujo condicional. Los bucles while, do-while y for repiten instrucciones. La recursividad necesita caso base y llamada recursiva. Las funciones devuelven valor; los procedimientos no.
