Si quiere descargar la presentación y los códigos fuente, dirijase a:
http://programaciondecomputadoresunalmzl.wikispaces.com/codigos_y_diapositivas
Le agradecería si me reporta los errores que encuentre en la diapositiva (daalvarez arroba unal punto edu punto co)
00/01 - Introduccion al curso y a la estadística descriptiva
02 - Conceptos fundamentales sobre tipos de datos en lenguaje C
1. 1
02 - Conceptos fundamentales
sobre el tratamiento de datos
Diego Andrés Alvarez Marín
Profesor Asociado
Universidad Nacional de Colombia
Sede Manizales
2. 2
Temario
● Tipos de datos
● Lógica binaria y álgebra de Boole
● Variables y constantes
● Cadenas de texto
● Asignaciones, operadores y precedencia de
operadores, expresiones
3. Tipos de datos
● Los tipos de datos determinan el conjunto de
valores que un objeto puede tomar y las
operaciones que se pueden realizar con ellas.
● Existen datos:
– caracteres: char
– numéricos: int, float, double
– booleanos (definidos en C99) _Bool
– definidos por el usuario: struct, union, enum (los
veremos más tarde)
– punteros
– complejos (definidos en C99) _Complex
4. Caracter (char)
● Representa un conjunto de 8 bits de datos que
varían entre 0 y 255 (256 números=28
), es
decir, tiene el tamaño de un byte
Algunos caracteres especiales
a r
Backspace b f
t ”
Escape (solo GNU) e n
o x
Backslash '
0 ?
Alerta (audible) Retorno de carro
Formfeed
Tabulador horizontal Comillas
Cambio de linea=rf
Número octal (ej: o32) Número hex (ej: xF3)
Apóstrofe
Nulo Pregunta
5.
6.
7. Tipos booleanos
NOTA: stdbool.h define las palabras
bool, false, true (definido en C99)
Definido en C99
http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/stdbool.h.html
Cualquier expresión
diferente de 0 es true, si
es igual a cero es false
10. Representación de números reales
en el PC
Ver:
● David Goldberg (1991). What Every Computer
Scientist Should Know About Floating-Point
Arithmetic. Computing Surveys, March 1991.
– https://ece.uwaterloo.ca/~dwharder/NumericalAnalysis/02Numerics/Double/paper.pdf
● http://en.wikipedia.org/wiki/Floating_point
● http://en.wikipedia.org/wiki/IEEE_floating_point
● http://en.wikipedia.org/wiki/Single-precision_floating-point_format
● http://en.wikipedia.org/wiki/Double-precision_floating-point_format
● http://en.wikipedia.org/wiki/Quadruple-precision_floating-point_format
11. Modificadores de tipos
● Son: signed, unsigned, short, long
● signed y unsigned sólo se aplican a char e int
● long se aplica a double
● No se usan con los tipos enum, struct, union,
void, float
signed unsigned
char char
0111 1111 127 127
1111 1111 -128 255
Bit de
signo
12. 32 bits
64 bits
80, 128 bits (depende del
compilador y del PC...
en mi casa 96 bits)
sinónimos
13. Tamaño de los datos
(la palabra clave sizeof)
● Los tamaños de los datos dependen de la
máquina y el compilador utilizado. Estos se
miden en bytes
sizeof(char) < sizeof(short) <= sizeof(int) <= sizeof(long)
sizeof(char) < sizeof(short) <= sizeof(float) <= sizeof(double)
● Se puede escribir también sizeof(3.123),
sizeof('m'), etc.
● Ver en http://en.wikipedia.org/wiki/sizeof los
otros usos de sizeof
14. MAX/MIN numérico
● Dependen de la plataforma
● Los máximos y los mínimos están definidos en
limits.h (enteros) y float.h (reales)
● Ver el archivo /usr/include/limits.h
● Ver el archivo /usr/include/float.h
16. Tipos de entero
(nota: estas constantes dependen del computador y pueden variar)
Ver: http://www.gnu.org/software/gnu-c-manual/gnu-c-manual.html#Integer-Types
bits MIN MAX MIN MAX
signed char -128 127
8 0 UCHAR_MAX 0 255
16 SHRT_MIN SHRT_MAX -32768 32767
16 0 USHRT_MAX 0 65535
32 INT_MIN INT_MAX -2147483648 2147483647
long int 32 LONG_MIN LONG_MAX
32 0 UINT_MAX 4294967295U
unsigned long int 0 ULONG_MAX
long long int 64 LLONG_MIN LLONG_MAX -9223372036854 775808LL 9223372036854 775807LL
CHAR_BIT
8
SCHAR_MIN
CHAR_MIN
SCHAR_MAX
CHAR_MAX
char
unsigned char
short
short int
signed short
signed short int
unsigned short
unsigned short int
int
signed
signed int
unsigned
unsigned int
21. Por lo tanto la próxima vez declare la variable
contar_ovejas como
unsigned long int o unsigned long long int
Fuente: https://xkcd.com/571/
22. DBL_EPSILON representa el número más pequeño posible que
puede sumársele a 1.0 para que (1.0 + DBL_EPSILON) > 1.0. En
MATLAB esta constante se llama "eps". DBL_EPSILON
representa la exactitud relativa de la aritmética del computador.
Observe que un double tiene 52 bits en su parte de fracción, por
lo que 2-52
= DBL_EPSILON = 2.22044604925031e-16 es la
mayor precisión posible.
Ver: http://en.wikipedia.org/wiki/Machine_epsilon
24. Big endian vs Little endian
● Se requiere tener en cuenta para aquellos tipos
de datos que ocupan varios bytes, ya que el
orden en el que se organizan los bytes es
importante
● Tiene que ver con el orden de como se
representan los bytes en memoria y en disco.
Es muy importante tenerlo en cuenta cuando
se van a trabajar con supercomputadoras.
● Ver: http://en.wikipedia.org/wiki/Endianness
25. Big endian vs Little endian
El término endianness designa el formato en el que se
almacenan los datos de más de un byte en un computador. El
problema es similar a los idiomas en los que se escriben de
derecha a izquierda, como el árabe, o el hebreo, frente a los que
se escriben de izquierda a derecha, pero trasladado de la
escritura al almacenamiento en memoria de los bytes.
El sistema big-endian adoptado por Motorola entre otros,
consiste en representar los bytes en el orden "natural": así el
valor hexadecimal 0x4A3B2C1D se codificaría en memoria en la
secuencia {4A, 3B, 2C, 1D}. En el sistema little-endian adoptado
por Intel, entre otros, el mismo valor se codificaría como {1D, 2C,
3B, 4A}, de manera que de este modo se hace más intuitivo el
acceso a datos, porque se efectúa fácilmente de manera
incremental de menos relevante a más relevante (siempre se
opera con incrementos de contador en la memoria).
27. El sistema big-endian consiste en representar los bytes en el orden
"natural": así el valor hexadecimal 0x4A3B2C1D se codificaría en
memoria en la secuencia {4A, 3B, 2C, 1D}. En el sistema little-
endian el mismo valor se codificaría como {1D, 2C, 3B, 4A}.
28. La librería stdint.h
El tamaño de una variable entera varía de sistema operativo
a sistema operativo y de computador a computador. En C99
se incluyen las librerías inttypes.h y stdint.h con el ánimo de
mejorar la portabilidad de los programas con respecto a las
variables enteras.
stdint.h define los siguientes tipos de entero:
29. La librería stdint.h
Se pueden definir variables enteras de N = 8, 16, 32 y 64 bits.
Adicionalmente, los tipos de entero se pueden clasificar en:
● Enteros de ancho exacto (exact-width integer): se
garantiza que ocuparán N bits.
● Enteros del mínimo ancho (least-width integer): son el tipo
de enteros más pequeño en la implementación.
● Enteros más veloces (fastest integer): son el tipo de entero
más rápido en la implementación.
● Punteros a entero (pointer integer): se garantiza que
contendrán un puntero.
● Enteros del máximo ancho (maximum-width integer): son
el tipo de enteros más grandes en la implementación.
30. Ejemplo de stdint.h
int64_t es:
● un long int en 32 bits (%ld)
● un long long int en 64 bits (%lld)
Finalmente, tenga en cuenta que el C99 define en
math.h los tipos float_t y double_t.
31. Números complejos
● Introducidos en el C99. Existen tres tipos:
– float _Complex
– double _Complex
– long double _Complex
● El C99 introduce la librería complex.h que hace
que utilizar números complejos sea fácil
– Define el tipo complex que es lo mismo que double
_Complex
– Define la constante I (i mayúscula) ... es un const
float _Complex
– http://en.wikipedia.org/wiki/Complex.h
– http://pubs.opengroup.org/onlinepubs/009604499/basedefs/complex.h.html
32.
33. Punteros
● Los punteros son un tipo de dato que guarda
direcciones de memoria (de variables,
constantes, funciones, etc)
int* x; // se puede escribir tambien int * x o int *x
int *x, *y; // dos punteros enteros
int *x, y; // un puntero a entero y una variable entera
● Si no se inicializa un puntero a una dirección de
memoria, este apunta a cualquier lugar de
memoria y por lo tanto si se usa, usted podría
hacer que el programa falle (crash).
36. Reglas para la creación de los nombres de
las variables/identificadores/nombres de
funciones/estructuras, etc...
● Pueden contener letras (A-Z, a-z), dígitos (0-9) y el
guión bajo _ . Ejemplo Radio_2 es válido
● El nombre debe comenzar con letras o con el guión
bajo: radio y _radio son válidos, 2radio no lo es.
● Las palabras clave (while, for, int, long, etc.) no se
pueden utilizar como nombres de variables
● Los nombre de variables son sensitivos a las
mayúsculas: area, Area, AREA y aREA son variables
diferentes
38. Las variables se deben declarar antes de usar, de
lo contrario los programas pueden tener
comportamientos inesperados.
Declaración de variables
tipo nombre_de_variable = [valor_inicial][,][...];
(lo que está en corchetes es opcional)
39. Declaración de variables
En el C89 se requería que las variables se
declararan antes de cualquier comando al
principio de un bloque. En el C99 (y de forma
similar al C++), las variables se pueden declarar
en cualquier lugar de un bloque.
En C89 double d; tenía que
haber estado junto a int c;
40. Constantes
●Son valores literales y fijos que se asignan a las
variables o que se utilizan para utilizar directamente
en las expresiones:
●Enteros: 3, 3UL, 0x12, 012
●Punto flotante (float, double): 3.1415, 3.1415F
●Caracteres: 'V', 'x4A', 'o101'
●Cadenas: "Pepito Perez", "Una cadenan"
●Enumeración:
– enum dias {lun, mar, mie, jue, vie, sab, dom}
– enum color {negro=1, gris, azul, rojo=10, verde, blanco}
41. Constantes enteras
● Si una secuencia de dígitos está precedida por
0x ó o 0X (cero equis), entonces la constante
se considera hexadecimal (0..9, A..F).
Ejemplos; 0xab2f, 0x88, 0xAB43, 0xaBcD, 0x1
● Si el primer dígito es 0 y el siguiente no es x ó
X, entonces la constante se considera octal
(0..7). Ejemplos; 057, 012, 03, 0241
● En el resto de los casos se considera decimal
(0..9). Ejemplo: 459, 23901, 8, 12
42. Existen varios tipos de datos enteros: enteros cortos,
largos, con signo y sin signo. Las constantes enteras se
clasifican en estas categorías agregando una secuencia
de una o más letras al final de la constante:
u, U: Unsigned integer type: sin signo.
l, L: Long integer type: entero largo.
Por ejemplo 45U es una contante unsigned int. 45UL es
una constante unsigned long int (las letras se pueden
poner en cualquier órden).
El ISO C99 considera los tipos long long int y unsigned
long long int. Uno puede utizar entonces dos "L"s para
obtener una constante long long int; agregue un "U" a
dicha constante para obtener una constante unsigned
long long int, como por ejemplo: 45ULL.
43. Constantes reales
● La parte entera o la parte decimal se puede
omitir, pero no ambas. Por ejemplo:
double a, b, c, d, e;
a = 4.7; b = 4.; c = 4; d = .7; e = 0.7;
● Se puede agregar una letra al final de una
constante numérica real para forzarla a que
sea de un tipo determinado. "f" o "F" significa
constante float; "l" o "L" significa constante long
double. Si no agrega letras, es una constante
double.
44. Cadenas de texto
● Se representan como arrays de caracteres
● C no limita la longitud de la cadena
● El final de la cadena está dado por un 0(cero) ó '0',
el cual no se indica explícitamente.
● Se separan 5 bytes de memoria (el 0 se cuenta):
– char cad[] = "hola";
● Se separan 10 bytes de memoria, pero la cadena solo
ocupa 5 bytes
– char cad[10] = "hola";
● Se separan 5 bytes de memoria. Se indica el final de
la cadena.
– char cad[] = {'h','o','l','a','0'};
45. Esta es una cadena constante:
"tutti frutti ice cream"
Estas cadenas se concatenan:
"tutti " "frutti" " ice " "cream"
Esta cadena tiene dos secuencias con códigos de
escape (comienzan por ):
""hello, world!""
46. Si una cadena es muy larga como para hacerla caber en
una sola línea, se puede utilizar el backslash para
escribirla en líneas diferentes:
"Today's special is a pastrami sandwich on rye bread with
a potato knish and a cherry soda."
Las cadenas adyacentes se concatenan automáticamente,
de modo tal que se pueden tener constantes cadena que
ocupan varias líneas. Por ejemplo:
"Tomorrow's special is a corned beef sandwich on "
"pumpernickel bread with a kasha knish and seltzer water."
es lo mismo que:
"Tomorrow's special is a corned beef sandwich on
pumpernickel bread with a kasha knish and seltzer water."
47. Operadores
● Los operadores especifican como se puede
manipular un objeto/variable
– Aritméticos: + - * / %
– Relacionales: > < >= <= == !=
– Lógicos: && || !
– De incremento/decremento: x++ y-- ++x --y
– Bit a bit: & | ^ ~ >> <<
– De asignación: = += -= *= /= %= &= |=
– Especiales: ? : , . -> & * sizeof
48. Operaciones aritméticas,
asignaciones
● Operaciones aritméticas binarias
x+y x-y x*y x/y x%y
● Operaciones aritméticas binarias con
asignación
x += y x -= y x *= y x /= y
x %= y
● Asignaciones (variable = expresión):
y = x + 4*y/(x - 2) + y;
49. En C99, la división de valores positivos
enteros se trunca siempre hacia cero. De
este modo 5/3 es 1. y -5/3 = -1. Tenga en
cuenta que esto no era verdad en C89, ya
que el redondeo podía ser hacia cero o hacia
menos infinito. Todo dependía del compilador
53. Operaciones de incremento
Tenga en cuenta que incrementar un puntero solo tiene
sentido si el nuevo puntero apunta a una dirección de
memoria válida.
57. ● Cualquier expresión diferente de cero es verdadero en C,
mientras que si es cero se considera falsa.
● Con &&: si la primera expresión es falsa, la segunda no se
evalúa:
if ((x == 5) && (y == 10)) printf ("x=5 y y=10");
● Con ||: si la primera expresión es verdadera, la segunda
no se evalúa:
if ((x == 5) || (y == 10)) printf ("x=5 o y=10");
● Negación:
if (!(x == 5)) printf ("x es diferente de 5");
Uno puede escribir código como (no recomendable):
if (foo && x++) bar();
Si foo es cero, entonces x no se incrementará y bar() no se
evaluará.
61. Comentarios
() de izquierda a derecha paréntesis (para cambiar prioridades)
1
() de izquierda a derecha llamado a función
[] de izquierda a derecha elemento de vector
-> . de izquierda a derecha
++ -- de izquierda a derecha Post-incremento y decremento
++ -- de derecha a izquierda Pre-incremento y decremento
+ - de derecha a izquierda Signo + o -
! ~ de derecha a izquierda NOT lógico y NOT binario
(tipo) de derecha a izquierda
* de derecha a izquierda operador “contenido de” en punteros
& de derecha a izquierda dirección de memoria de una variable
sizeof de derecha a izquierda tamaño de
Prece-
dencia
Grupo de
operadores
Orden de
evaluación
0
mayor
Prioridad
selección de elemento de estructura
de forma directa (.) o con un
Puntero (->)
2
operadores
unarios
conversión de tipo. Ejemplo (int),
(char)
Precedencia de operadores
62. 3 * / %
4 + -
5 << >>
6 < <= > >=
7 == !=
8 & ^ |
9 && ||
10 ?:
11
,
Prece-
dencia
Grupo de
operadores
Orden de
evaluación
Comentarios
de izquierda a derecha multiplicación, división, módulo
de izquierda a derecha suma y resta
de izquierda a derecha operadores de desplazamiento bit a bit
de izquierda a derecha
menor que, menor o igual que, mayor
que, mayor o igual que
de izquierda a derecha igual a, diferente de
de izquierda a derecha AND binario, XOR binario, OR binario
de izquierda a derecha AND lógico, OR lógico
de derecha a izquierda operador si?entonces:de lo contrario
= += -= *= /=
%= &= ^= |=
<<= >>=
de derecha a izquierda asignaciones
12
prioridad
más
baja
de izquierda a derecha coma (se usa en el for)
Precedencia de operadores
63. Constantes
● Las constantes no pueden ser modificadas.
● Su valor no cambia durante la ejecución del
programa
compilador
preprocesador
65. Conversión entre tipos de datos
● Cuando se mezclan expresiones de una
precisión baja con unas de precisión alta, C
prefiere utilizar la precisión alta:
char → int → long int→ float → double → long double
● Ejemplos:
– 3 + 3.13 → 6.13 esto es: (int) + (float) → (float)
– 'a' + 300 → 397 esto es: (char) + (int) → (int)
67. Por la forma como el PC almacena los reales,
no es posible representar 3.3 y 3.4 exactamente
68. Convertir cadenas a números y
números a cadenas
#include <stdlib.h>
#include <stdio.h>
69. Ambito de las variables
● Las variables se dividen en: globales y locales.
● Las variables locales sólo existen en el bloque
en el cual se definieron { } y se deben declarar
antes de utilizarlas:
Aquí ya no existe tmp2
Aquí existe tmp y tmp2
Aquí no existe ni tmp ni tmp2
Aquí existe tmp
70. Ambito de variables por bloques
Las variables (locales) sólo existen en el bloque
en el cual se definieron. Los bloques se definen
por { }
Si aquí se hace una referencia a b, aparecería un
error de compilación
71. Librerías de precisión aritmética
arbitraría
En caso que usted tenga que utilizar muchos más
decimales que los que se pueden almacenar en
un long double, se sugiere utilizar una librería
como:
● GNU Multiple Precision Arithmetic Library http://gmplib.org/
● GNU MPFR Library http://www.mpfr.org/
ambas librerías soportan tantos decimales como
la memoria del computador pueda almacenar.