• No se han encontrado resultados

Uniones y campos de bits

In document Curso de C para dummies.pdf (página 184-189)

9.2 ¿Qué son los punteros?

11. Otras características avanzadas de C

11.4 Uniones y campos de bits

Conocemos lo que es un struct: un dato formado por varios “trozos” de información de distinto tipo. Pero C también tiene dos tipos especiales de “struct”, de manejo más avanzado. Son las uniones y los campos de bits.

Una unión recuerda a un “struct” normal, con la diferencia de que sus “campos=” comparten el mismo espacio de memoria:

union {

char letra; /* 1 byte */ int numero; /* 4 bytes */ } ejemplo;

En este caso, la variable “ejemplo” ocupa 4 bytes en memoria (suponiendo que estemos trabajando en un compilador de 32 bits, como lo son la mayoría de los de Windows y Linux). El primer byte está compartido por “letra” y por “numero”, y los tres últimos bytes sólo pertenecen a “numero”.

Si hacemos

ejemplo.numero = 25; ejemplo.letra = 50;

Veremos que “ejemplo.numero” ya no vale 25, puesto que al modificar “ejemplo.letra” estamos cambiando su primer byte. Ahora “ejemplo.numero” valdría 50 o un número mucho más grande, según si el ordenador que estamos utilizando almacena en primer lugar el byte más significativo o el menos significativo.

Un campo de bits es un elemento de un registro (struct), que se define basándose en su tamaño en bits. Se define de forma muy parecida (pero no igual) a un "struct" normal, indicando el número de bits que se debe reservar a cada elemento:

struct campo_de_bits { int bit_1 : 1; int bits_2_a_5 : 4; int bit_6 : 1; int bits_7_a_16 : 10; } variableDeBits; Esta variable ocuparía 1+4+1+10 = 16 bits (2 bytes). Los campos de bits pueden ser interesantes cuando queramos optimizar al máximo el espacio ocupado por nuestro datos.

11.5. El operador coma

Cuando vimos la orden “for”, siempre usábamos una única variable como contador, pero esto no tiene por qué ser siempre así. Vamos a verlo con un ejemplo: /*---*/ /* Ejemplo en C nº 100: */ /* c100.c */ /* */ /* Operador coma (1) */ /* */ /* Curso de C, */ /* Nacho Cabanes */ /*---*/ #include <stdio.h> main(){ int i, j;

for (i=0,j=1; i<=5, j<=30; i++, j+=2) printf("i vale %d y j vale %d.\n", i, j); }

Vamos a ver qué hace este "for":

• Los valores iniciales son i=0, j=1.

• Se repetirá mientras que i <= 5, j <= 30.

• Al final de cada paso, i aumenta en una unidad, y j en dos unidades.

El único problema está en saber cúando terminará el bucle: si se parará en cuanto se cumpla una de las dos condiciones o si tendrán que cumplirse las dos.

i vale 0 y j vale 1. i vale 1 y j vale 3. i vale 2 y j vale 5. i vale 3 y j vale 7. i vale 4 y j vale 9. i vale 5 y j vale 11. i vale 6 y j vale 13. i vale 7 y j vale 15. i vale 8 y j vale 17. i vale 9 y j vale 19. i vale 10 y j vale 21. i vale 11 y j vale 23. i vale 12 y j vale 25. i vale 13 y j vale 27. i vale 14 y j vale 29.

Como podemos observar, llega un momento en que deja de cumplise que i<=5, pero el programa sigue avanzando: no se sale del bucle “for” hasta que se cumplen las dos condiciones (realmente, hasta que se cumple la segunda).

La idea es que, en general, si se usa el operador coma para separar dos expresiones, nuestro compilador evalúa la primera expresión, luego la segunda, y devuelve como valor el resultado de la segunda. Veámoslo con un segundo ejemplo algo más rebuscado

/*---*/ /* Ejemplo en C nº 101: */ /* c101.c */ /* */ /* Operador coma (2) */ /* */ /* Curso de C, */ /* Nacho Cabanes */ /*---*/ #include <stdio.h> main(){ int i, j, k; k = ((i=5), (j=6)); printf("i=%d, j=%d, k=%d", i, j, k); }

Aun así, en la práctica, el único uso habitual del operador coma es el primero que hemos visto: utilizar dos condiciones simultáneas para controlar un bucle “for”.

11.6. Enumeraciones

Cuando tenemos varias constantes, cuyos valores son números enteros, y especialmente si son números enteros consecutivos, tenemos una forma abreviada de definirlos. Se trata de enumerarlos:

enum diasSemana { LUNES, MARTES, MIERCOLES, JUEVES, VIERNES, SABADO, DOMINGO };

(Al igual que las constantes de cualquier otro tipo, se suele escribir en mayúsculas para recordar en cualquier parte que se sepa "de un vistazo" que son constantes, no variables)

La primera constante valdrá 0, y las demás irán aumentando de una en una, de modo que en nuestro caso valen:

LUNES = 0, MARTES = 1, MIERCOLES = 2, JUEVES = 3, VIERNES = 4, SABADO = 5, DOMINGO = 6

Si queremos que los valores no sean exactamente estos, podemos dar valor a cualquiera de las contantes, y las siguientes irán aumentando de uno en uno. Por ejemplo, si escribimos

enum diasSemana { LUNES=1, MARTES, MIERCOLES, JUEVES=6, VIERNES, SABADO=10, DOMINGO };

Ahora sus valores son:

LUNES = 1, MARTES = 2, MIERCOLES = 3, JUEVES = 6, VIERNES = 7, SABADO = 10, DOMINGO = 11

11.7. Definición de tipos

El tipo de una variable nos indica el rango de valores que puede tomar. Tenemos creados para nosotros los tipos básicos, pero puede que nos interese crear nuestros propios tipos de variables, para lo que usamos “typedef”. El formato es

typedef tipo nombre;

Lo que hacemos es darle un nuevo nombre a un tipo de datos. Puede ser cómodo para hacer más legible nuestros programas. Por ejemplo, alguien que conozca Pascal o Java, puede echar en falta un tipo de datos “boolean”, que permita hacer comparaciones un poco más legibles, siguiendo esta estructura:

if (encontrado == FALSE) ... o bien como if (datosCorrectos == TRUE) ... /*---*/ /* Ejemplo en C nº 102: */ /* c102.c */ /* */ /* Definición de tipos (1) */ /* */ /* Curso de C, */ /* Nacho Cabanes */ /*---*/ #include <stdio.h>

#define VALIDA 711 /* Clave correcta */

#define TRUE 1 /* Nostalgia de los boolean */ #define FALSE 0

typedef int boolean; /* Definimos un par de tipos */ typedef int integer;

integer clave; /* Y dos variables */ boolean acertado;

int main() { do {

printf("Introduzca su clave numérica: "); scanf("%d", &clave);

acertado = (clave == VALIDA);

if (acertado == FALSE) printf("No válida!\n"); }

while (acertado != TRUE); printf("Aceptada.\n"); return 0;

}

También podemos usar "typedef" para dar un nombre corto a todo un struct:

/*---*/ /* Ejemplo en C nº 103: */ /* c103.c */ /* */ /* Definición de tipos (2) */ /* */ /* Curso de C, */ /* Nacho Cabanes */ /*---*/ #include <stdio.h>

typedef struct { /* Defino el tipo "datos" */ int valor;

float coste; char ref; } datos;

datos ejemplo; /* Y creo una variable de ese tipo */ int main() {

ejemplo.valor = 34; ejemplo.coste = 1200.5; ejemplo.ref = 'A';

printf("El valor es %d", ejemplo.valor); return 0;

}

In document Curso de C para dummies.pdf (página 184-189)