1
02 - Conceptos fundamentales sobre el tratamiento de datos
Diego Andrés Alvarez MarínProfesor Asociado
Universidad Nacional de ColombiaSede Manizales
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
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
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 \rBackspace \b \f
\t \”Escape (solo GNU) \e \n
\o \xBackslash \\ \'
\0 \?
Alerta (audible) Retorno de carroFormfeed
Tabulador horizontal ComillasCambio de linea=\r\f
Número octal (ej: \o32) Número hex (ej: \xF3)Apóstrofe
Nulo Pregunta
Tipos booleanos
NOTA: stdbool.h define las palabrasbool, 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
Númerosenteros
(int)
Número real:float, double, long double
float
double
long double
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
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
32 bits
64 bits
80, 128 bits (depende del compilador y del PC... en mi casa 96 bits)
sinónimos
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 bytessizeof(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
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
unsigned char
unsigned char
Ver: http://www.gnu.org/software/libc/manual/html_node/Floating-Point-Parameters.html
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 2147483647long int 32 LONG_MIN LONG_MAX
32 0 UINT_MAX 4294967295Uunsigned long int 0 ULONG_MAXlong long int 64 LLONG_MIN LLONG_MAX -9223372036854 775808LL 9223372036854 775807LL
CHAR_BIT8
SCHAR_MINCHAR_MIN
SCHAR_MAXCHAR_MAX
charunsigned charshortshort intsigned shortsigned short intunsigned shortunsigned short intintsignedsigned int
unsignedunsigned int
Evite usar float
MAX/MIN numérico
(overflow)
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/
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
Como obtener DBL_EPSILON
Recuerde que:DBL_EPSILON=2-52
=2.22044604925031e-16
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
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).
Big endian vs Little endian
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}.
La librería stdint.hEl 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:
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.
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.
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
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).
35
Variable
● Una variable es un nombre o referencia a un valor guardado de la memoria del sistema
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
Palabras clave
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)
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;
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 cadena\n"●Enumeración:
– enum dias {lun, mar, mie, jue, vie, sab, dom}
– enum color {negro=1, gris, azul, rojo=10, verde, blanco}
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
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.
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.
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'};
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!\""
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."
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
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;
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
Operadores relacionales
El resultado de esta operación es 1 o 0, lo que se entiendecomo verdadero o falso
Igualdad de dos números
reales
Esto es demasiado, porque solo se guardan 15 dígitos significativos para un double
Operadores de asignación
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.
Operadores lógicos
El resultado de esta operación es 1 o 0, lo que se entiendecomo verdadero o falso
Lógica binaria y álgebra de Boole
NOT AND
OR
XOR
● 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á.
Operadores bit a bit
Bitwise Logical Operators
Los operadores & | ^ ~ se pueden utilizar únicamente con char o unsigned int.
Bit shifting
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 deoperadores
Orden de evaluación
0mayor
Prioridad
selección de elemento de estructura de forma directa (.) o con unPuntero (->)
2operadores
unarios
conversión de tipo. Ejemplo (int), (char)
Precedencia de operadores
3 * / %
4 + -
5 << >>
6 < <= > >=
7 == !=
8 & ^ |
9 && ||
10 ?:
11
,
Prece-dencia
Grupo deoperadores
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
12prioridad
másbaja
de izquierda a derecha coma (se usa en el for)
Precedencia de operadores
Constantes
● Las constantes no pueden ser modificadas.● Su valor no cambia durante la ejecución del
programa
compilador
preprocesador
Expresiones
● Una expresión es una combinación de valores, variables, operadores y funciones
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)
Moldeo (Casting)
● Para convertir de un tipo de dato a otro (casting), haga lo siguiente:
Por la forma como el PC almacena los reales, no es posible representar 3.3 y 3.4 exactamente
Convertir cadenas a números y números a cadenas
#include <stdlib.h>
#include <stdio.h>
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
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 unerror de compilación
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.
Wide characters (wchar)
Material basado en:
● http://www.slideshare.net/amraldo/introduction-to-c-programming-7898353
● http://www.slideshare.net/petdance/just-enough-c-for-open-source-programmers
● http://www.gnu.org/software/gnu-c-manual/gnu-c-manual.html
● Wikipedia