Resumen
Esta clase cierra la segunda unidad del curso, dedicada a los datos y sus tipos. Reconstruye la cadena de conceptos que va de la variable a la constante que el compilador vigila, pasando por la representación binaria de los enteros y sus dos desbordamientos, los reales aproximados y la tolerancia, los caracteres como códigos y las conversiones que pierden información; separa lo que de ello vale en cualquier lenguaje de lo que es propio de C++; reúne el comportamiento indefinido de la unidad, con lo que detecta el compilador, lo que detecta el detector y lo que no detecta nadie; repite en su evaluación de salida las destrezas de la entrada; y termina con seis desafíos que combinan la unidad entera.
Objetivos de aprendizaje
- Elegir y justificar el tipo de cada dato de un problema según los valores que puede tomar, la exactitud que exige y las operaciones que se harán con él.
- Predecir los efectos de los límites de representación en un programa dado: el desbordamiento de los enteros, el redondeo de la coma flotante y la pérdida de información de una conversión.
- Usar constantes con nombre y conversiones explícitas, y explicar qué comprueba el compilador en cada caso.
- Reconocer el comportamiento indefinido de la unidad y decir, para cada caso, qué lo detecta y cómo se previene.
- Separar, en lo aprendido en la unidad, lo que vale en cualquier lenguaje de lo que es propio de C++.
Lo logrado en la unidad
La unidad se propuso enseñar que todo dato vive en la memoria con un tipo que fija qué valores puede tomar, cuánto ocupa y qué operaciones admite, y que esos límites tienen consecuencias observables. El propósito se ha cumplido apoyándose solo en lo que la introducción declaró por sabido: el ciclo de compilar y ejecutar con las opciones del curso, la salida con formato, la lectura con std::cin y la lectura de los mensajes del compilador. El programa de las cuatro cuentas con que la introducción planteó el problema puede ahora explicarse línea por línea, y corregirse.
Variables y memoria
La clase Variables y memoria estableció que una variable es una casilla de la memoria con un nombre, un tipo fijo y un valor que cambia, y que el tipo fija su tamaño, que sizeof mide. Distinguió la inicialización de la asignación, mostró que las llaves rechazan una conversión con pérdida, y enseñó que la asignación copia y no liga, y que el valor reemplazado se pierde, de donde se sigue la variable auxiliar del intercambio. Definió el estado de un programa como el conjunto de los valores de sus variables y enseñó a seguirlo con una tabla de traza. Fijó las convenciones de los nombres y cerró con el primer comportamiento indefinido de la unidad: la lectura de una variable que nunca recibió valor.
Los enteros y su representación
La clase Los enteros y su representación enseñó la notación posicional en las bases 10, 2 y 16. De que un tipo tenga bits dedujo su rango: patrones, que sin signo representan de a y con signo, en complemento a dos, de a , con un negativo más que positivos. Distinguió los dos desbordamientos: el de los enteros sin signo, que es aritmética módulo y está definido (0u - 1 vale ), y el de los enteros con signo, que es comportamiento indefinido y que el detector detiene. Mostró que comparar un entero con signo con uno sin signo convierte el primero, de modo que es falso, y terminó con un criterio para elegir el tipo entero según el rango previsible del dato.
Los números de coma flotante
La clase Los números de coma flotante mostró que un real se guarda como signo, exponente y mantisa binaria, de modo que los valores representables son un conjunto finito de racionales con denominador potencia de 2. De ello se siguió que no existe en la máquina: en su lugar se guarda el doble más próximo, y 0.1 + 0.2 se escribe 0.30000000000000004. La clase acotó el error de cada redondeo, mostró que los errores se acumulan y que la suma deja de ser asociativa; de donde dedujo que dos reales calculados no se comparan con ==, sino por su distancia, con una tolerancia justificada. Fijó double como tipo real por omisión, y presentó el infinito y el valor no numérico, NaN.
Caracteres, booleanos, conversiones y constantes
La clase Caracteres, booleanos, conversiones y constantes mostró que un tipo es una regla para leer los bits: un char guarda un byte cuyo valor es el código ASCII del carácter, y como las cifras y las letras tienen códigos consecutivos, '7' - '0' vale 7; un bool es verdadero o falso, y cualquier número distinto de cero se convierte en verdadero. Estudió las conversiones implícitas y estableció que la conversión ocurre dentro de la operación, según el tipo de los operandos, y no al guardar el resultado: double r{7 / 2} vale 3. Enseñó a escribir la conversión querida con static_cast, que no evita la pérdida, sino que la declara; precisó que las llaves rechazan el estrechamiento, y mostró el tercer comportamiento indefinido de la unidad, la conversión a entero de un real que no cabe. Cerró con las constantes (const, constexpr y static_assert), el tipo de los literales y auto.
Cargando el contenido…