Guía de ejercicios

Representación de datos

Recordad que, excepto cuando se indique lo contrario, en los ejercicios de este capítulo queda limitado el uso de operadores y estructuras de C a:

  • operaciones sobre bits (&, |, ~)
  • desplazamientos a izquierda y derecha (<<, >>)
  • sumas y restas (+, -)
  • igualdad y desigualdad (==, !=)

Clase 20/03

2.61

Escribir expresiones en C que devuelvan 1 cuando cada una de las las siguientes condiciones sean verdaderas, o 0 cuando no. Asumir que x es de tipo uint32_t.

  1. Si cualquier bit de x es 1
  2. Si cualquier bit de x es 0
  3. Si cualquier bit en el byte menos significativo de x es 1
  4. Si cualquier bit en el byte más significativo de x es 0

El código debe seguir las reglas de programación para enteros a nivel bit. Como restricción adicional, no se permite el uso de operadores de igualdad (==) y desigualdad (!=).

2.66

Implementar la función:

1
int leftmost_one(uint32_t val);

que devuelve una máscara indicando el bit más significativo en val que está a 1. Por ejemplo, se devuelve 0x8000 para val=0xFF00 y 0x4000 para val=0x6600.

2.72

La siguiente función copia un valor de tipo int en un buffer de tamaño dado maxbytes bytes (obsérvese que la comprobación del tamaño se hace, de manera algo artificial, mediante una resta):

1
2
3
4
void copy_int(int val, void *buf, int maxbytes) {
    if (maxbytes - sizeof(val) >= 0)
        memcpy(buf, &val, sizeof(val));
}

Testeando el código en detalle, se puede ver que el valor siempre se copia al buffer, includo cuando maxbytes tiene un valor muy chico.

  1. Explicar por qué el condicional siempre da verdadero. (Ayuda: El operador sizeof devuelve un valor de tipo size_t.)
  2. Reescribir el condicional de modo que funcione correctamente.

Clase 13/03

2.60

Implementar la función:

1
uint32_t replace_byte(uint32_t val, int i, uint8_t rempl);

que devuelve el entero val con su i-ésimo byte cambiado al valor de rempl. Los bytes se numeran asignando i=0 al byte menos significativo e i=3 al más significativo.

2.64

Implementar la función:

1
int any_odd_one(uint32_t val);

que devuelve 1 si val tiene algún bit impar a 1, o 0 si todos sus bits impares están a 0. Por ejemplo, la función devuelve 0 para val=5 y 1 para val=6.

2.68

Implementar la función:

1
uint32_t lower_one_mask(int n);

que, dado un entero entre 1 y 32 (inclusive) devuelve una máscara con ese número de bits activos (comenzando por el menos significativo). Ejemplos: para n=6, la función devuelve 0x3F.