Herramientas de usuario

Herramientas del sitio


tipos

Diferencias

Muestra las diferencias entre dos versiones de la página.

Enlace a la vista de comparación

Ambos lados, revisión anteriorRevisión previa
Próxima revisión
Revisión previa
tipos [2014/08/06 15:48] – [El sistema de tipos de C] lmateutipos [2020/03/17 23:38] (actual) – [Inferencia de tipos] lmateu
Línea 7: Línea 7:
   * Las reglas de inferencia del tipo de una expresión   * Las reglas de inferencia del tipo de una expresión
   * Como se definen nuevos tipos de datos   * Como se definen nuevos tipos de datos
- 
-==== Tipos de datos primitivos ==== 
  
 C ofrece los siguientes tipos primitivos: C ofrece los siguientes tipos primitivos:
Línea 17: Línea 15:
 C no define tipos especiales para valores booleanos (como en Java: boolean) o para los strings (como en Java: String). C no define tipos especiales para valores booleanos (como en Java: boolean) o para los strings (como en Java: String).
  
-==== Representación de números en binario ====+===== Tipos numéricos enteros =====
  
 Los enteros se almacenan internamente en binario. Por ejemplo: Los enteros se almacenan internamente en binario. Por ejemplo:
Línea 55: Línea 53:
  
   * Observe que el rango de representación no es simétrico: en 32 bits -2<sup>31</sup> es representable, ¡pero 2<sup>31</sup> no lo es!   * Observe que el rango de representación no es simétrico: en 32 bits -2<sup>31</sup> es representable, ¡pero 2<sup>31</sup> no lo es!
-  * Los número negativos se representan en complemento de 2 (esto se estudia en Arquitectura de Computadores).+  * Los número negativos se representan en complemento de 2.
   * En la plataforma Windows de 64 bits, el tipo long es de 32 bits (no es de 64 bits como en Unix).   * En la plataforma Windows de 64 bits, el tipo long es de 32 bits (no es de 64 bits como en Unix).
   * A partir del estandar C99 existe el tipo long long.  Se especifica que debe ser de al menos 8 bytes.   * A partir del estandar C99 existe el tipo long long.  Se especifica que debe ser de al menos 8 bytes.
-  * Observe que aún cuando ya no se fabrican PCs de 32 bits (basados en la arquitectura x86), la mayoría de los smartphones y tablets de hoy usan procesadores ARM de 32 bits.+  * Observe que aún cuando los procesadores de PCs y smartphones son de 64 bits, la mayoría de los smartphones funcionan en modo 32 bits, a no ser que tengan al menos 4 GB de memoria RAM.
   * Tampoco se fabrican PCs de 16 bits, pero se venden muchos procesadores para sistemas embebidos que son de 16 bits, con precios insignificantes al lado de sus hermanos de 32 o 64 bits.  Por razones de costos nadie colocaría un procesador de 32 o 64 bits para controlar una lavadora.   * Tampoco se fabrican PCs de 16 bits, pero se venden muchos procesadores para sistemas embebidos que son de 16 bits, con precios insignificantes al lado de sus hermanos de 32 o 64 bits.  Por razones de costos nadie colocaría un procesador de 32 o 64 bits para controlar una lavadora.
 +
 +Advertencia: Cuando se opera con números enteros y se produce un desborde, el runtime de C no genera ningún tipo de error.  El resultado simplemente se trunca al tamaño que debe poseer el resultado.  El tamaño está especificado por las reglas de inferencia de tipos que veremos más abajo en esta misma página.
  
 ==== Representación de números negativos ==== ==== Representación de números negativos ====
Línea 103: Línea 103:
 Observe que si x e y son sin signo, x-y todavía se calcula como x+~y+1. Observe que si x e y son sin signo, x-y todavía se calcula como x+~y+1.
  
-==== Tipos reales ====+===== Tipos reales =====
  
   * Los números reales se representan en notación de punto flotante (en binario).   * Los números reales se representan en notación de punto flotante (en binario).
Línea 124: Línea 124:
 implementaban por software.  Por lo mismo usar reales era muy lento. implementaban por software.  Por lo mismo usar reales era muy lento.
  
-==== Expresiones y operadores ====+Cuando se opera con números reales y se produce un desborde, el resultado es un //not a number// (NaN).  Un NaN operado con cualquier otro número siempre resulta ser un NaN. 
 + 
 +===== Expresiones y operadores =====
  
 Java heredó los operadores de C y C++. Java heredó los operadores de C y C++.
 Para más detalles sobre los operadores de C consultar la [[http://es.wikipedia.org/wiki/Operadores_de_C_y_C%2B%2B|wikipedia]] Para más detalles sobre los operadores de C consultar la [[http://es.wikipedia.org/wiki/Operadores_de_C_y_C%2B%2B|wikipedia]]
  
-=== Precedencia ===+==== Precedencia ====
  
 La precedencia de los operadores es la que dicta cómo se hace la parentización en caso de ambigüedad.  Por ejemplo la expresión //a+b*c// es ambigua porque se podría interpretar como //(a+b)*c// o como //a+(b*c)// Pero como C especifica que * tiene mayor precedencia que + entonces la expresión es equivalente a //a+(b*c)//. La precedencia de los operadores es la que dicta cómo se hace la parentización en caso de ambigüedad.  Por ejemplo la expresión //a+b*c// es ambigua porque se podría interpretar como //(a+b)*c// o como //a+(b*c)// Pero como C especifica que * tiene mayor precedencia que + entonces la expresión es equivalente a //a+(b*c)//.
Línea 135: Línea 137:
 Si ha escrito una expresión y tiene dudas sobre la precedencia consulte la [[http://es.wikipedia.org/wiki/Operadores_de_C_y_C%2B%2B|wikipedia]] o alternativamente use parentización explícita. Si ha escrito una expresión y tiene dudas sobre la precedencia consulte la [[http://es.wikipedia.org/wiki/Operadores_de_C_y_C%2B%2B|wikipedia]] o alternativamente use parentización explícita.
  
-=== Asociatividad ===+==== Asociatividad ====
  
-En caso de ambigüedad con //operadores de la misma precedencia// se usa la regla de asociatividad para determinar la parentización implícita.  Por ejemplo la expresión //a+b-c// es ambigua y los operadores + y - tienen la misma precedencia.  La regla de asociatividad para + y - es de izquierda a derecha y por lo tanto la expresión equivalente es //(a+b)-c//.+En caso de ambigüedad con //operadores de la misma precedencia// se usa la regla de asociatividad para determinar la parentización implícita.  Por ejemplo la expresión //a-b+c// es ambigua y los operadores + y - tienen la misma precedencia.  La regla de asociatividad para + y - es de izquierda a derecha y por lo tanto la expresión equivalente es //(a-b)+c//.
  
 Para la mayoría de los operadores la regla de asociatividad es de izquierda a derecha pero hay excepciones: el operador =.  La expresión //a=b=c// es equivalente a //a=(b=c)// De hecho escribir //(a=b)=c// es un error. Para la mayoría de los operadores la regla de asociatividad es de izquierda a derecha pero hay excepciones: el operador =.  La expresión //a=b=c// es equivalente a //a=(b=c)// De hecho escribir //(a=b)=c// es un error.
  
-La otra excepción son los operadores de indirección y post-incremento, ambos con la misma precedencia.  La expresión //*p++// es ambigua porque se puede referir a //(*p)++// o bien //*(p++)// La regla de asociatividad para estos operadores es de derecha a izquierda de modo que la interpretación correcta es //*(p++)//.+La otra excepción son los operadores de indirección y post-incremento, ambos con la misma precedencia.  La expresión //*p++// es ambigua porque se puede referir a //(*p)++// o bien //*(p++)// La regla de asociatividad para estos operadores es de derecha a izquierda de modo que la interpretación correcta es //*(p++)//.  El operador unario //*// es el operador de indirección y será estudiado en la sección de punteros
  
 Un resumen de los operadores, su precedencia y asociatividad se encuentra en: [[http://users.dcc.uchile.cl/~lmateu/CC3301/apuntes/LenguajeC/#9]] Un resumen de los operadores, su precedencia y asociatividad se encuentra en: [[http://users.dcc.uchile.cl/~lmateu/CC3301/apuntes/LenguajeC/#9]]
Línea 147: Línea 149:
    
  
-==== Inferencia de tipos ====+===== Inferencia de tipos =====
  
 Las reglas de inferencia de tipos indican cual es el tipo de la expresión: e<sub>1</sub> operador e<sub>2</sub>, Las reglas de inferencia de tipos indican cual es el tipo de la expresión: e<sub>1</sub> operador e<sub>2</sub>,
Línea 195: Línea 197:
   double x= (double)(a+1);   double x= (double)(a+1);
      
-Por lo tanto //a+1// se realiza en 32 bits con signo.  El resultado en binario es un 1 seguido de 31 ceros, que corresponde al valor entero -2147483648.+Por lo tanto //a+1// se realiza en 32 bits con signo.  El resultado en binario es un 1 seguido de 31 ceros, que corresponde al valor entero -2147483648.  Ese es el valor incorrecto que queda almacenado finalmente en x.  Y no 2147483648 como debería ser.
  
-**Ejercicio**: Reescriba la instrucción de asignación cambiando todas las conversiones implícitas conversiones explícitas.+**Ejercicio**: Reescriba la instrucción de asignación cambiando todas las conversiones implícitas conversiones explícitas.
  
 <code> <code>
Línea 207: Línea 209:
 </code> </code>
  
 +Resumen:
  
-=== Mezcla de operandos con y sin signo ===+  * El rango de un tipo numérico es el intervalo de números que puede representar. 
 +  * Los tipos numéricos están estrictamente ordenados por su rango: 
 +    * %% char < short <int <long <long long < float < double %% 
 +  * Cuando se realiza una operación numéricas entre tipos distintos, el operando de un tipo con rango menor se convierte implícitamente al tipo del otro operando. 
 +  * No se realizan operaciones aritméticas con un tipo de rango inferior a int.  Es decir cuando un operando es de tipo char o short se convierte implícitamente al menos a un int.
  
-En Ansi C también se especifica que si un operando es con signo el otro sin signo, entonces el operando sin signo se convierte implícitamente a un tipo con signo y la operación se realiza con signo.+==== Mezcla de operandos con y sin signo ====
  
-==== Definición de nuevos tipos ====+A partir de Ansi C se especifica que si un operando es con signo y el otro sin signo, entonces el operando sin signo se convierte implícitamente a un tipo con signo y la operación se realiza con signo.  Esto significa que si un operando es unsigned int y se suma con un int, entonces el primero se convierte a int.  ¡Cuidado! En esta conversión se podría producir un desborde.
  
-En C se definen nuevos tipos con struct, union, enum y typedef.  Estos temas serán abordados más adelante. +===== El costo de las operaciones =====
- +
-==== El costo de las operaciones ====+
  
 Dado que C es un lenguaje en donde interesa la eficiencia, resulta importante conocer cual es el costo de las operaciones aritméticas en términos de su latencia.  La latencia de una operación es la cantidad de ciclos del reloj del procesador que deben pasar para poder usar el resultado de esa operación. Dado que C es un lenguaje en donde interesa la eficiencia, resulta importante conocer cual es el costo de las operaciones aritméticas en términos de su latencia.  La latencia de una operación es la cantidad de ciclos del reloj del procesador que deben pasar para poder usar el resultado de esa operación.
Línea 233: Línea 238:
 En los procesadores menos recientes (Sandy Bridge) pueden ser 1 ciclo por cada 2 bits del divisor e incluso En los procesadores menos recientes (Sandy Bridge) pueden ser 1 ciclo por cada 2 bits del divisor e incluso
 1 ciclo por cada bit del divisor (más lento). 1 ciclo por cada bit del divisor (más lento).
 +
 +===== Definición de nuevos tipos =====
 +
 +En C se definen nuevos tipos con struct, union, enum y typedef.  Estos temas serán abordados más adelante.
  
tipos.1407340106.txt.gz · Última modificación: 2014/08/06 15:48 por lmateu