--- title: "Tipos de dato." date: 2022-01-24T20:32:57+01:00 draft: false weight: 3 --- C es un lenguaje tipado, lo que implica que cada vez que quieras crear una variable tienes que especificar su tipo de dato. Aquí veremos unos cuantos útiles en el día a día programando en C. ## Tipos de datos básicos. Considero tipos de datos básicos a aquellos que no se pueden usar para crear estructuras de datos: `int`: Almacena un número de 32 bits. `long int`: Varía entre arquitecturas y sistemas operativos, en GNU/Linux de 64bits almacena un número de 64 bits, en GNU/Linux de 32 bits almacena un número de 32 bits. `long long int`: Almacena un número de 64 bits. `unsigned int`: Almacena un número de 32 bits sin signo, lo que implica que tiene un bit más para poder extenderse hacia el lado de los números positivos. `unsigned long int`: ... `size_t`: Almacena un número tan grande como el tamaño máximo de las estructuras de datos en el sistema operativo. (En GNU/Linux unsigned long int); `char`: Almacena un carácter. (8 bits) Los carácteres utf-8 que conocemos pueden extenderse por más de un char de C. ## Tipos de datos compuestos. `array`: Un array es una estructura de datos compuesta que te permite tener varios datos del mismo tipo dentro del mismo. Ejemplo: ```c #include int main (int argc, char **argv) { char hola[] = { 'h', 'o', 'l', 'a', '\0' }; printf ("%s\n", hola); } ``` `struct`: Un struct te permite almacenar varios tipos de datos dentro de una única variable. Ejemplo: ```c #include struct prueba { int numero; char *string; }; int main (int argc, char **argv) { char hola[] = { 'h', 'o', 'l', 'a', '\0' }; struct prueba prueba = { 42, hola }; printf ("%d %s\n", prueba.numero, prueba.string); } ``` C nos otorga fácilidades para trabajar con structs por ejemplo si prueba fuese un puntero `struct prueba *` podríamos acceder a los tipos de datos internos con `prueba->numero` en lugar de tener que dereferenciar el puntero. Ejemplo: ```c #include struct prueba { int numero; char *string; }; int main (int argc, char **argv) { char hola[] = { 'h', 'o', 'l', 'a', '\0' }; struct prueba prueba = { 42, hola }; struct prueba *pruebaPtr = &prueba; printf ("%d %s\n", (*pruebaPtr).numero, (*pruebaPtr).string); } ``` ```c #include struct prueba { int numero; char *string; }; int main (int argc, char **argv) { char hola[] = { 'h', 'o', 'l', 'a', '\0' }; struct prueba prueba = { 42, hola }; struct prueba *pruebaPtr = &prueba; printf ("%d %s\n", pruebaPtr->numero, pruebaPtr->string); } ``` ## Punteros Cuando un tipo de dato compuesto va a vivir más que la función es muy conveniente que el mismo sea un puntero, veremos como alocar memoria para un puntero y como trabajar con el. Ejemplo: ```c #include #include struct prueba { int numero; char *hola; }; struct prueba * create_struct_prueba_allocated (char *hola) { struct prueba *prueba = malloc (sizeof *prueba); prueba->numero = 42; prueba->hola = hola; return prueba; } char * create_array_hola_allocated (size_t *hola_len) { char hola[] = { 'h', 'o', 'l', 'a', '\0' }; size_t hola_to_return_len = sizeof hola; char *hola_to_return = malloc (hola_to_return_len * sizeof *hola_to_return); for (size_t i = 0; i < hola_to_return_len; i++) { hola_to_return[i] = hola[i]; } if (hola_len) { *hola_len = hola_to_return_len; } return hola_to_return; } int main (int argc, char **argv) { size_t hola_len = 0; char *hola = create_array_hola_allocated (&hola_len); struct prueba *prueba = create_struct_prueba_allocated (hola); printf ("%d %s\n", prueba->numero, prueba->hola); free (hola); hola = NULL; free (prueba); prueba = NULL; } ``` Notas: * `sizeof` solo se puede usar en un array en la función que ha sido creado, por eso exportamos su tamaño como un puntero aunque en este caso no lo usemos. * `&` Convierte una variable en un puntero. * `*` Detras de un puntero lo dereferencia. * `free` Para evitar malgastar memoria deallocamos la memoria tras usarla. * `malloc` Al allocar un array multiplicamos su tamaño por el tamaño del tipo de dato que contiene. Ejemplo: ``` char *array = malloc (42 * sizeof char); ``` O ``` char *array = malloc (42 * sizeof *array); ``` ## Enums Un enum te permite darles nombres a listas de numeros, por ejemplo: ```c #include #include typedef enum { COLOR_CYAN = 1, COLOR_VERDE = 2, COLOR_AMARILLO = 4 } Color; struct prueba { int numero; char *hola; Color color; }; struct prueba * create_struct_prueba_allocated (char *hola) { struct prueba *prueba = malloc (sizeof *prueba); prueba->numero = 42; prueba->hola = hola; prueba->color = COLOR_CYAN; return prueba; } char * create_array_hola_allocated (size_t *hola_len) { char hola[] = { 'h', 'o', 'l', 'a', '\0' }; size_t hola_to_return_len = sizeof hola; char *hola_to_return = malloc (hola_to_return_len * sizeof *hola_to_return); for (size_t i = 0; i < hola_to_return_len; i++) { hola_to_return[i] = hola[i]; } if (hola_len) { *hola_len = hola_to_return_len; } return hola_to_return; } int main (int argc, char **argv) { size_t hola_len = 0; char *hola = create_array_hola_allocated (&hola_len); struct prueba *prueba = create_struct_prueba_allocated (hola); printf ("%d %d %s\n", prueba->numero, prueba->color, prueba->hola); free (hola); hola = NULL; free (prueba); prueba = NULL; } ```