Algoritmos y Lenguaje de Programación, Sección 1 Tipos de datos en C Tipos de Datos • Representación de datos en C está relacionada con la arquitectura del computador )Memoria se direcciona por bytes )Procesadores tienen registros de 1, 2, 4, 8 bytes Mario Medina C. mariomedina@udec.cl • Un dato cualquiera tiene )Un tipo (caracter, entero, punto flotante) )Un valor (que puede ser indeterminado) )Una posición de memoria donde está almacenado Tipo de dato char Tipo de dato short int • Al menos 8 bits • Al menos 16 bits • Puede abreviarse a short • Rangos mínimos )Debe poder almacenar un caracter ASCII • Rangos mínimos )signed char: -128 a 127 )unsigned char: 0 a 255 )short: -32768 (-215) a 32767 (215 – 1) )unsigned short: 0 a 65535 (216 - 1) • Rango de char depende del compilador )Por omisión, char puede ser signed o unsigned Tipo de dato int • Al menos 16 bits • Rangos mínimos )int: -32768 (-215) a 32767 (215 – 1) )unsigned int: 0 a 65535 (216 - 1) • 16 bits, 32 bits o 64 bits? )A elección de la implementación )Generalmente tamaño de registros de CPU ©Mario Medina C. Tipo de dato long int • Al menos 32 bits • Puede abreviarse como long • Rangos mínimos )long: -2147483648 (-231) a 2147483647 (231 – 1) )unsigned long: 0 a 4294967295 (232 – 1) 1 Algoritmos y Lenguaje de Programación, Sección 1 Tipo de dato long long int Archivo<limits.h> • Al menos 64 bits • Puede abreviarse como long long • Introducido en estándar ISO C99 • Rangos mínimos • Archivo que define los límites usados por el compilador -263 263 )long long: a –1 )unsigned long long: 0 a 264 – 1 Constantes en <limits.h> Tipo Min. signed Max. signed Max. unsigned char SCHAR_MIN SCHAR_MAX UCHAR_MAX short SHRT_MIN SHRT_MAX USHRT_MAX int INT_MIN INT_MAX UINT_MAX long LONG_MIN LONG_MAX ULONG_MAX )Residente en \Dev-Cpp\include • Define rangos de los tipos de datos )CHAR_BIT: número de bits por byte ` 8 bits )CHAR_MIN: valor mínimo para char )CHAR_MAX: valor máximo para char Operador sizeof() • Operador retorna el tamaño de un tipo de datos en bytes )sizeof(long) ≥ sizeof(int) ≥ sizeof(short) )sizeof(char) = 1 )sizeof(short) = 2 )sizeof(long) = 4 )sizeof(int) = 2, 4 o 8 )sizeof(long long) = 8 Constantes char Constantes enteras • Letras, números y símbolos ASCII son constantes de tipo char • Números tienen tipo int por omisión )‘A’ = ASCII 65 )‘F’ = ASCII 70 )‘A’ + ‘F’ = 135 )‘\t’: tab (ASCII 9) )‘\n’: avance de línea (ASCII 13) )‘\0’: ASCII 0 (no confundir con ‘0’: ASCII 48) ©Mario Medina C. )Números long int se especifican con L ó l )234: tipo int )234U: tipo unsigned int )234L: tipo long int • Números hexadecimales precedidos de 0x )0x234 = 23416 = 56410 • Números octales precedidos de 0 )0234 = 2348 = 15610 2 Algoritmos y Lenguaje de Programación, Sección 1 Porqué usar constantes? Promoción de enteros • Conveniencia y claridad en el código • Código puede mezclar tipos • El tipo más corto es promovido al tipo mayor antes de la operación • Promoción no pierde información • ‘B’ + 5 ⇒ char + int numero = numero – 48; numero = numero – 060; numero = numero – ‘0’; • Todos hacen lo mismo )Todos corresponden a la misma secuencia de bits: 001110002 Rebalse de enteros int k; (k * 1024); • Qué pasa si int es de 16 bits? )Si k es menor de 32, resultado cabe en 16 bits )Si k es mayor de 32, rebalse! )Este es un error de tiempo de ejecución • Solución: usar constante long y promoción k * 1024L; Rebalse en sumas en C )Resultado es de tipo int Curiosidades del C • 0 igual a 0U: Verdadero • -1 < 0: Verdadero • -1 < 0U: Falso )Operación se realiza en aritmética sin signo • 2147483647 > -2147483647 - 1: V • 2147483647U > -2147483647 - 1: F )Operación se realiza en aritmética sin signo • 2147483647 > (int) 2147483648U: V )Cast convierte número sin signo a con signo Rebalse en suma sin signo • Rebalse (Overflow) se produce si resultado de suma excede capacidad de representación del tipo de datos )Operación se transforma en aritmética modular • Aritmética entera con signo )Puede ocurrir rebalse positivo • Aritmética con signo (complemento a 2) )Pueden ocurrir rebalses positivos y negativos ©Mario Medina C. 3 Algoritmos y Lenguaje de Programación, Sección 1 Rebalse en suma con signo Ejercicios de enteros T w o 's c o m p le m e n t a d d itio n (4 -b it w o rd ) 8 6 4 2 0 6 -2 4 2 -4 0 -6 -2 -8 -4 -8 -6 -4 -6 -2 0 2 4 • Indique si estas aseveraciones 1. x < 0 implica (x*2) < 0 2. ux >= 0 son V ó F 3. x&7==7 implica (x<<30) < 0 )Suponga 4. ux > -1 int x; 5. x > y implica –x < -y int y; 6. x*x >= 0 unsigned ux; 7. x>0 && y>0 implica x+y > 0 8. x >= 0 implica –x <= 0 9. x <= 0 implica –x >= 0 -8 6 Enumeraciones Enumeraciones • Permite definir secuencias de enteros • Usa constantes simbólicas • Enumeración siempre comienza en 0 )enum dias {LUNES, MARTES, MIERCOLES, JUEVES, VIERNES, SABADO, DOMINGO}; )Una vez definidas, no se deben redefinir! • Equivalente a )int LUNES = 0, MARTES = 1, MIERCOLES = 2, JUEVES = 3, VIERNES = 4, SABADO = 5, DOMINGO = 6; Punto flotante • Números decimales representados en codificación llamada “punto flotante” )Pueden darse valores explícitamente )Puede usar números enteros positivos y negativos )Constantes no especificadas toman valor de constante anterior + 1 )enum numeros {UNO = 1,DOS, CUATRO = 4, CINCO, OCHO = 8}; )X = CINCO + OCHO; /* X vale 13 */ Archivo <float.h> Tipo Mínimo ` Tamaño típico: 32 bits float FLT_MIN FLT_MAX )double: precisión doble double DBL_MIN DBL_MAX Long double LDBL_MIN LDBL_MAX )float: precisión simple ` Tamaño típico: 64 bits Máximo )long double: precisión extendida ` Tamaño típico: 80 bits ©Mario Medina C. 4 Algoritmos y Lenguaje de Programación, Sección 1 Rangos de tipos (aproximados) Constantes de punto flotante • float • Números con punto decimal tienen tipo double por omisión )10-38 ≤ float ≤ 1038 )-1038 ≤ float ≤ -10-38 )2.3421: tipo double • double • Números float se especifican con F ó f )10-308 ≤ double ≤ 10308 )-10308 ≤ double ≤ -10-308 )2.3421f: tipo float • long double ≤ long double ≤ )-104932 ≤ long double ≤ -10-4932 )10-4932 104932 • Números long double se especifican con L ól )2.3421L: tipo long double Constantes de punto flotante Aritmética de punto flotante • Pueden especificarse también en notación científica • Actualmente, en forma generalizada, se usa formato IEEE-754 • Codifica números de la forma (-1)s·0.m·2e )2.34e21 equivalente a 2.34x1021 )6.02e-23 equivalente a 6.02x10-23 • Constantes también pueden ser números hexadecimales )0x14p10 equivalente a 20x210 = 2048010 ` P indica exponente binario )s corresponde al signo )m corresponde a la mantisa )e corresponde al exponente • En computación, siempre se usa base 2 • Exponente e puede ser positivo o negativo Números de precisión simple Números de precisión doble • Precisión simple (float) utiliza 32 bits • Precisión simple (double) utiliza 64 bits )1 bit de signo s, 23 de mantisa m y 8 de exponente e )1 bit de signo s, 52 de mantisa m y 11 de exponente e • Exponente e va entre -126 y +127 )Codificado como e+127 • Mantisa m toma valores 0 ≤ m < 1 )Parte fraccionaria f es 1+ m (“1 implícito”) • Exponente e va entre -1022 y +1023 )Codificado como e+1023 • Mantisa m toma valores 0 ≤ m < 1 )Parte fraccionaria f es 1+ m (“1 implícito”) • Estos son los valores normalizados )No representan el 0! ©Mario Medina C. 5 Algoritmos y Lenguaje de Programación, Sección 1 Valores denormalizados Valores especiales • Bits del exponente e toman valor 0 • Representación del 0 )Precisión simple: exponente es -127 )Precisión doble: exponente es -1023 • Valor fraccionario f es valor de la mantisa m )Sin el 1 implícito • Permiten representar números cercanos al 0 )Bit de signo s es 0, bits del exponente e son 0s y mantisa m es 0 )-0.0: Bit de signo s es 1, bits del exponente e son 0s y mantisa m es 0 • Bits del exponente e son sólo 1s )Si mantisa m es 0, número es +∞ ó -∞ )Si mantisa m es diferente de 0, número es NaN (Not a Number) ` Ejemplo: Raíz de -1 Ejemplo de conversión a punto flotante • Convertir entero 12345 a precisión simple )1234510 es 110000001110012 )Forma normalizada: 1.10000001110012x213 )Eliminando el 1 y completando a 23 bits, se tiene m = 10000001110010000000000 )El exponente es e = 127 + 13 = 14010 = 100011002 )El signo s es 0 (número positivo) )El resultado completo es 0x4640E400, o 0 10001100 100000011100100000000002 Ejemplos precisión simple Ejemplo de conversión • Convertir 0x40490FDB a su equivalente decimal en punto flotante )010000000100100100001111110010112 )Signo 0 implica número positivo )Exponente 128 implica e es 1 )Mantisa 100100100001111110010112 implica número con el 1 implícito es 1.100100100001111110010112, que es 1.570710 )Número es entonces1.5707x21=3.1414 Ejemplos precisión doble Valor decimal Descripción Exponente Fracción Valor Valor decimal Descripción Exponente Fracción Valor Cero 00…00 0….00 0 0.0 Cero 00…00 0….00 0 1.4x10-45 Denorm. mínimo 00…00 0….01 2-52x2-1022 4.9x10-324 0.0 Denorm. mínimo 00…00 0….01 2-23x2-126 Denorm. máximo 00…00 1….11 (1-2-23) x2-126 1.2x10-38 Denorm. máximo 00…00 1….11 (1-2-52) x2-1022 2.2x10-308 Normal mínimo 00…01 0….00 1x2-126 1.2x10-38 Normal mínimo 00…01 0….00 1x2-1022 2.2x10-308 Uno 01…11 0….00 1x20 1.0 Uno 01…11 0….00 1x20 Normal máximo 11…10 1….11 (2-2-23)x2126 3.4x1038 Normal máximo 11…10 1….11 (2-2-52)x2126 ©Mario Medina C. 1.0 1.8x10308 6 Algoritmos y Lenguaje de Programación, Sección 1 Punto flotante en Intel x86 • Procesadores Intel x86 tiene registros especiales de 80 bits para punto flotante )Formato tiene 1 bit de signo, 63 de mantisa y 15 de exponente ` Incluye además 1 bit para el 1 implícito )Todas las operaciones de punto flotante entre registros se realizan usando números de 80 bits ` Resultados luego se truncan y/o redondean a 64 o 32 bits )Estándar C tiene tipo de dato long double para forzar este comportamiento Ejercicios de punto flotante • Indique si estas aseveraciones son V ó F )Suponga int x; float f; double d; 1. 2. 3. 4. 5. 6. 7. x == (int) (float) x; x == (int) (double) x; f == (float) (double) f; d == (float) d; f == -(-f); 2/3 == 2/3.0; d < 0.0 implica (d*2) < 0.0 8. d > f implica –f > -d 9. d*d >= 0.0 10.(d + f) – d == f Otros tipos de datos Conversión de tipos • _Bool • Conversión entre enteros y punto flotante se hace mediante un cast )Introducido por ISO C99 ` No todos los compiladores lo incluyen )Definido en <stdbool.h> ` No está presente en Dev-C++ )Define valores de true y false como ` false es 0 ` true es 1 )Se fuerza la conversión a otro tipo indicando el tipo nuevo entre paréntesis int a = (int) 4.566; /* a vale 4 */ float b = (float) 2; /* b vale 2.0 */ double c = (double) ‘A’; /* c vale 65.0 */ )También puede usarse bool en vez de _Bool Conversión de tipos • Ojo con los paréntesis! )Importante al usar división entera float float float float float a b c d e = = = = = 5/2; /* a vale 2.0 */ 5.0/2; /* b vale 2.5 */ (float) 5/2; /* c vale 2.5 */ (float) (5/2); /* d vale 2.0 */ ((float) 5)/2; /* e vale 2.5 */ Conversión de tipos • Es posible usar un cast para convertir de un número entero a otro de menor tamaño )Compilador se va a quejar, pero es posible! )Resultado es indefinido char a = 424343242; • También puede hacerse con números de punto flotante float b = 4.5342e45; ©Mario Medina C. 7