Semana 3 — Bits: cómo se representan los datos
Objetivos
- Convertir números entre decimal, binario y hexadecimal.
- Explicar por qué ocurre el overflow y por qué
0.1 + 0.2no da exactamente0.3. - Distinguir carácter, código y byte, y explicar cómo UTF-8 guarda la
ñ. - Guardar el historial de un trabajo con los comandos básicos de Git.
Teoría — Bits: binario, hexadecimal, enteros, decimales y texto
Lectura: Apuntes, semana 3.
Temas:
- Sistemas posicionales: decimal, binario y hexadecimal. Bytes y múltiplos.
- Enteros con signo y complemento a dos. Overflow.
- Punto flotante en lo esencial. Error común: comparar
doublecon==. El dinero se guarda en céntimos. chares un número pequeño: ASCII.- Unicode y UTF-8: por qué
ñocupa 2 bytes ynocupa 1.
Laboratorio — Bits a mano y primeros pasos con Git
- Convertir a mano 202 a binario y a hexadecimal. Comprobarlo con
printf("%x"). - Sumar 1 al mayor
int, con el valor leído porscanf, compilando con-fsanitize=undefined. Leer el mensaje. - Imprimir
0.1 + 0.2con%.20f. - Crear un archivo con
añoy mirarlo conxxd. Identificar los bytes de lañ. - Crear un repositorio con
git init, hacer dos commits y revisargit status,git diffygit log.
Preguntas de repaso
- Conviertan
10110110a decimal y a hexadecimal. - ¿Cuál es el mayor entero con signo de 8 bits? ¿Cómo se escribe -1 en complemento a dos?
- ¿Por qué no conviene guardar el saldo de una cuenta en un
double? - Un archivo tiene 5 caracteres y 7 bytes en UTF-8. ¿Cómo es posible?
- ¿Para qué sirven
git addygit commit, y en qué se diferencian?
Código de la semana
Compilar y probar dentro del contenedor del curso con make y make test.
Ejemplos (16)Errores (2)Pruebas (2)Laboratorio (4)Compilación (1)
Ejemplos
Los programas que usan los apuntes y la clase.
// Un mismo número, escrito en decimal y en hexadecimal.
#include <stdio.h>
int main(void) {
int n = 202;
int m = 0xCA; // 0x indica que el literal está en hexadecimal
printf("%d en decimal\n", n);
printf("%x en hexadecimal, con minúsculas\n", n);
printf("%X en hexadecimal, con mayúsculas\n", n);
printf("0xCA vale %d\n", m);
return 0;
}// Un char guarda un número: el código del carácter.
#include <stdio.h>
int main(void) {
char letter = 'A';
char digit = '7';
printf("%c tiene el código %d\n", letter, letter);
printf("%c tiene el código %d\n", letter + 1, letter + 1);
printf("'a' - 'A' = %d\n", 'a' - 'A');
printf("minúscula de %c: %c\n", letter, letter + 32);
printf("%c tiene el código %d\n", digit, digit);
printf("'7' - '0' = %d\n", digit - '0');
return 0;
}// Lee un byte. Si vale 128 o más, char lo muestra distinto según la plataforma.
#include <limits.h>
#include <stdio.h>
int main(void) {
char c = 0;
int read_count = scanf("%c", &c);
printf("scanf leyó %d dato(s)\n", read_count);
printf("CHAR_MIN = %d, CHAR_MAX = %d\n", CHAR_MIN, CHAR_MAX);
printf("como char: %d\n", c);
printf("como unsigned char: %d\n", (unsigned char) c);
return 0;
}// Comparar double con == falla; se compara con una tolerancia.
#include <math.h>
#include <stdio.h>
int main(void) {
double sum = 0.1 + 0.2;
double target = 0.3;
double tolerance = 0.000000001;
printf("sum == target vale %d\n", sum == target);
printf("fabs(sum - target) < tolerance vale %d\n", fabs(sum - target) < tolerance);
return 0;
}// Un caso exacto y dos límites de double: los errores se acumulan y la precisión se acaba.
#include <stdio.h>
int main(void) {
double half = 0.5;
double quarter = 0.25;
printf("0.5 + 0.25 = %.20f\n", half + quarter);
double tenths = 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1;
printf("diez veces 0.1 = %.20f\n", tenths);
double big = 9007199254740992.0; // 2 elevado a 53
double bigger = big + 1.0;
printf("big = %.1f\n", big);
printf("big + 1 = %.1f\n", bigger);
return 0;
}// 0.1 + 0.2 no da exactamente 0.3.
#include <stdio.h>
int main(void) {
double a = 0.1;
double b = 0.2;
double c = 0.3;
double sum = a + b;
printf("con %%f: %f\n", sum);
printf("0.1 = %.20f\n", a);
printf("0.2 = %.20f\n", b);
printf("0.3 = %.20f\n", c);
printf("0.1 + 0.2 = %.20f\n", sum);
printf("diferencia = %.20f\n", sum - c);
// Una comparación vale 1 si es verdadera y 0 si es falsa.
printf("sum == c vale %d\n", sum == c);
return 0;
}// Escribe los primeros 9 bits de la parte fraccionaria de un número entre 0 y 1.
#include <stdio.h>
int main(void) {
double x = 0.0;
int read_count = scanf("%lf", &x);
printf("scanf leyó %d dato(s)\n", read_count);
// Cada paso duplica x. La parte entera, 0 o 1, es el bit; el cast la obtiene.
x = x * 2;
int b1 = (int) x;
x = x - b1;
x = x * 2;
int b2 = (int) x;
x = x - b2;
x = x * 2;
int b3 = (int) x;
x = x - b3;
x = x * 2;
int b4 = (int) x;
x = x - b4;
x = x * 2;
int b5 = (int) x;
x = x - b5;
x = x * 2;
int b6 = (int) x;
x = x - b6;
x = x * 2;
int b7 = (int) x;
x = x - b7;
x = x * 2;
int b8 = (int) x;
x = x - b8;
x = x * 2;
int b9 = (int) x;
printf("0.%d%d%d%d%d%d%d%d%d...\n", b1, b2, b3, b4, b5, b6, b7, b8, b9);
return 0;
}// Lee 8 dígitos binarios y escribe el número en decimal y en hexadecimal.
#include <stdio.h>
int main(void) {
int value = 0;
int bit = 0;
int read_count = 0;
// %1d lee un solo dígito. scanf devuelve 1 cada vez que lo logra.
read_count = read_count + scanf("%1d", &bit);
value = value * 2 + bit;
read_count = read_count + scanf("%1d", &bit);
value = value * 2 + bit;
read_count = read_count + scanf("%1d", &bit);
value = value * 2 + bit;
read_count = read_count + scanf("%1d", &bit);
value = value * 2 + bit;
read_count = read_count + scanf("%1d", &bit);
value = value * 2 + bit;
read_count = read_count + scanf("%1d", &bit);
value = value * 2 + bit;
read_count = read_count + scanf("%1d", &bit);
value = value * 2 + bit;
read_count = read_count + scanf("%1d", &bit);
value = value * 2 + bit;
printf("scanf leyó %d dígitos\n", read_count);
printf("decimal: %d\n", value);
printf("hexadecimal: %x\n", value);
return 0;
}// El mismo cálculo de dinero en soles con double y en céntimos con int.
#include <stdio.h>
int main(void) {
double price = 1.10;
double total = price * 3;
printf("3 x 1.10 con double: %.20f\n", total);
printf("lo mismo con %%.2f: %.2f\n", total);
double balance = 1.00 - 0.10 - 0.10 - 0.10 - 0.10 - 0.10 - 0.10 - 0.10 - 0.10 - 0.10 - 0.10;
printf("saldo con double: %.20f\n", balance);
int price_cents = 110;
int total_cents = price_cents * 3;
printf("3 x 110 céntimos: %d\n", total_cents);
printf("en soles: S/ %d.%02d\n", total_cents / 100, total_cents % 100);
int balance_cents = 100 - 10 - 10 - 10 - 10 - 10 - 10 - 10 - 10 - 10 - 10;
printf("saldo en céntimos: %d\n", balance_cents);
return 0;
}// Suma 1 a un int leído con scanf. Con INT_MAX se produce overflow.
#include <stdio.h>
int main(void) {
int n = 0;
int read_count = scanf("%d", &n);
printf("scanf leyó %d dato(s), n = %d\n", read_count, n);
int next = n + 1;
printf("n + 1 = %d\n", next);
return 0;
}// Lee 4 bytes y escribe cada uno en hexadecimal. %c lee un byte, no un carácter.
#include <stdio.h>
int main(void) {
char b0 = 0;
char b1 = 0;
char b2 = 0;
char b3 = 0;
int read_count = scanf("%c%c%c%c", &b0, &b1, &b2, &b3);
printf("scanf leyó %d byte(s)\n", read_count);
// El cast evita que un byte de 128 o más se vea negativo donde char tiene signo.
printf("%02x %02x %02x %02x\n", (unsigned char) b0, (unsigned char) b1,
(unsigned char) b2, (unsigned char) b3);
return 0;
}// Cuánto ocupa cada tipo y cuáles son los límites de los enteros.
#include <limits.h>
#include <stdio.h>
int main(void) {
printf("bits en un byte: %d\n", CHAR_BIT);
printf("sizeof(char) = %zu\n", sizeof(char));
printf("sizeof(int) = %zu\n", sizeof(int));
printf("sizeof(double) = %zu\n", sizeof(double));
printf("INT_MAX = %d\n", INT_MAX);
printf("INT_MIN = %d\n", INT_MIN);
return 0;
}// Escribe en binario un número de 0 a 255, con divisiones sucesivas entre 2.
#include <stdio.h>
int main(void) {
int n = 0;
// Mostramos cuántos datos leyó scanf. Con if, la próxima semana, ya podremos reaccionar.
int read_count = scanf("%d", &n);
printf("scanf leyó %d dato(s)\n", read_count);
int b0 = n % 2;
n = n / 2;
int b1 = n % 2;
n = n / 2;
int b2 = n % 2;
n = n / 2;
int b3 = n % 2;
n = n / 2;
int b4 = n % 2;
n = n / 2;
int b5 = n % 2;
n = n / 2;
int b6 = n % 2;
n = n / 2;
int b7 = n % 2;
// El primer resto es el bit de menor peso: se escribe al final.
printf("%d%d%d%d%d%d%d%d\n", b7, b6, b5, b4, b3, b2, b1, b0);
return 0;
}// Muestra el patrón de bits de un entero de -128 a 127, en complemento a dos.
#include <stdio.h>
int main(void) {
int x = 0;
int read_count = scanf("%d", &x);
printf("scanf leyó %d dato(s)\n", read_count);
// Sin if: si x es negativo da x + 256; si no, da x. Solo vale de -128 a 127.
int pattern = (x + 256) % 256;
printf("%d en 8 bits: %d%d%d%d%d%d%d%d\n", x,
pattern / 128 % 2, pattern / 64 % 2, pattern / 32 % 2, pattern / 16 % 2,
pattern / 8 % 2, pattern / 4 % 2, pattern / 2 % 2, pattern % 2);
// %x espera un valor sin signo: por eso el cast. Es el int completo, de 32 bits.
printf("%d en un int: %08x\n", x, (unsigned int) x);
return 0;
}// Los tipos sin signo sí dan la vuelta: C lo define así.
#include <stdio.h>
int main(void) {
unsigned char b = 255;
printf("b = %d\n", b);
b = b + 1;
printf("b = %d\n", b);
return 0;
}// Calcula los dos bytes UTF-8 de un código Unicode de 128 a 2047.
#include <stdio.h>
int main(void) {
int code = 0;
int read_count = scanf("%d", &code);
printf("scanf leyó %d dato(s)\n", read_count);
// Sin if no podemos rechazar otros códigos: fuera del rango, el resultado no sirve.
int first = 192 + code / 64; // 110xxxxx: los 5 bits altos
int second = 128 + code % 64; // 10xxxxxx: los 6 bits bajos
printf("bytes: %x %x\n", first, second);
printf("carácter: %c%c\n", first, second);
return 0;
}Errores
Ejemplos con errores a propósito: no compilan, fallan o dan un resultado incorrecto. Los apuntes explican cada uno.
// Error a propósito: la ñ no cabe en un char. No forma parte de make.
#include <stdio.h>
int main(void) {
char c = 'ñ';
printf("%c\n", c);
return 0;
}// Error a propósito: el compilador ve el overflow al compilar. No forma parte de make.
#include <limits.h>
#include <stdio.h>
int main(void) {
int next = INT_MAX + 1;
printf("%d\n", next);
return 0;
}Pruebas
Comprueban lo que afirman los apuntes; se ejecutan con make test.
"""Pruebas de los ejemplos de la semana 3: comparan la salida real de cada programa
con lo que dicen los apuntes. Se corren con `make test`."""
import re
import subprocess
import unittest
from pathlib import Path
HERE = Path(__file__).resolve().parent
BUILD = HERE / "build"
PROGRAMS = sorted(p for p in HERE.glob("*.c"))
def run(name, stdin=""):
if isinstance(stdin, str):
stdin = stdin.encode()
return subprocess.run([str(BUILD / name)], input=stdin, capture_output=True, timeout=20)
def out(name, stdin=""):
result = run(name, stdin)
return result.stdout.decode()
def compile_c(source, target, *flags):
return subprocess.run(["gcc", "-Wall", "-Wextra", "-std=c17", *flags, "-o", str(target), str(source)],
capture_output=True, text=True, cwd=HERE)
class Warnings(unittest.TestCase):
def test_no_warnings(self):
for source in PROGRAMS:
with self.subTest(source=source.name):
result = subprocess.run(["gcc", "-Wall", "-Wextra", "-Werror", "-std=c17", "-fsyntax-only", str(source)],
capture_output=True, text=True)
self.assertEqual(result.returncode, 0, result.stderr)
class Bases(unittest.TestCase):
def test_to_binary(self):
self.assertEqual(out("to_binary", "202\n"), "scanf leyó 1 dato(s)\n11001010\n")
self.assertEqual(out("to_binary", "182\n"), "scanf leyó 1 dato(s)\n10110110\n")
def test_to_binary_bad_input(self):
self.assertEqual(out("to_binary", "hola\n"), "scanf leyó 0 dato(s)\n00000000\n")
def test_from_binary(self):
self.assertEqual(out("from_binary", "10110110\n"),
"scanf leyó 8 dígitos\ndecimal: 182\nhexadecimal: b6\n")
def test_bases(self):
self.assertEqual(out("bases"), "202 en decimal\n"
"ca en hexadecimal, con minúsculas\n"
"CA en hexadecimal, con mayúsculas\n"
"0xCA vale 202\n")
def test_multiples(self):
self.assertEqual(f"{500 * 10**9 / 2**30:.2f}", "465.66")
self.assertEqual(100 * 10**6 / 8 / 10**6, 12.5)
self.assertEqual(2**31 - 1, 2147483647)
class Integers(unittest.TestCase):
def test_sizes(self):
self.assertEqual(out("sizes"), "bits en un byte: 8\n"
"sizeof(char) = 1\n"
"sizeof(int) = 4\n"
"sizeof(double) = 8\n"
"INT_MAX = 2147483647\n"
"INT_MIN = -2147483648\n")
def test_twos_complement(self):
table = {5: ("00000101", "00000005"), -1: ("11111111", "ffffffff"),
-3: ("11111101", "fffffffd"), -128: ("10000000", "ffffff80"),
127: ("01111111", "0000007f")}
for x, (bits, word) in table.items():
with self.subTest(x=x):
self.assertEqual(out("twos_complement", f"{x}\n"),
f"scanf leyó 1 dato(s)\n{x} en 8 bits: {bits}\n{x} en un int: {word}\n")
def test_overflow_reported(self):
result = run("overflow", "2147483647\n")
self.assertIn("overflow.c:9:9: runtime error: signed integer overflow: "
"2147483647 + 1 cannot be represented in type 'int'", result.stderr.decode())
def test_no_overflow(self):
result = run("overflow", "41\n")
self.assertEqual(result.stdout.decode(), "scanf leyó 1 dato(s), n = 41\nn + 1 = 42\n")
self.assertEqual(result.stderr, b"")
def test_overflow_bad_input(self):
self.assertEqual(out("overflow", "hola\n"), "scanf leyó 0 dato(s), n = 0\nn + 1 = 1\n")
def test_constant_overflow_warns(self):
result = compile_c("bad/constant_overflow.c", BUILD / "constant_overflow")
self.assertIn("warning: integer overflow in expression", result.stderr)
def test_unsigned_wrap(self):
result = run("unsigned_wrap")
self.assertEqual(result.stdout.decode(), "b = 255\nb = 0\n")
self.assertEqual(result.stderr, b"")
class Floats(unittest.TestCase):
def test_float_sum(self):
self.assertEqual(out("float_sum"), "con %f: 0.300000\n"
"0.1 = 0.10000000000000000555\n"
"0.2 = 0.20000000000000001110\n"
"0.3 = 0.29999999999999998890\n"
"0.1 + 0.2 = 0.30000000000000004441\n"
"diferencia = 0.00000000000000005551\n"
"sum == c vale 0\n")
def test_float_limits(self):
self.assertEqual(out("float_limits"), "0.5 + 0.25 = 0.75000000000000000000\n"
"diez veces 0.1 = 0.99999999999999988898\n"
"big = 9007199254740992.0\n"
"big + 1 = 9007199254740992.0\n")
def test_compare_doubles(self):
self.assertEqual(out("compare_doubles"), "sum == target vale 0\n"
"fabs(sum - target) < tolerance vale 1\n")
def test_money(self):
self.assertEqual(out("money"), "3 x 1.10 con double: 3.30000000000000026645\n"
"lo mismo con %.2f: 3.30\n"
"saldo con double: 0.00000000000000013878\n"
"3 x 110 céntimos: 330\n"
"en soles: S/ 3.30\n"
"saldo en céntimos: 0\n")
def test_fraction_to_binary(self):
self.assertEqual(out("fraction_to_binary", "0.1\n"), "scanf leyó 1 dato(s)\n0.000110011...\n")
self.assertEqual(out("fraction_to_binary", "0.75\n"), "scanf leyó 1 dato(s)\n0.110000000...\n")
def test_tenth_doubling(self):
# Los bits de 0.1 de la tabla de los apuntes, con fracciones exactas.
from fractions import Fraction
x = Fraction(1, 10)
bits = ""
for _ in range(9):
x *= 2
bits += str(int(x))
x -= int(x)
self.assertEqual(bits, "000110011")
class Text(unittest.TestCase):
def test_char_codes(self):
self.assertEqual(out("char_codes"), "A tiene el código 65\n"
"B tiene el código 66\n"
"'a' - 'A' = 32\n"
"minúscula de A: a\n"
"7 tiene el código 55\n"
"'7' - '0' = 7\n")
def test_char_sign_both_platforms(self):
# El signo de char depende de la plataforma: se comprueban las dos variantes.
cases = {"-fsigned-char": ("CHAR_MIN = -128, CHAR_MAX = 127", "como char: -61"),
"-funsigned-char": ("CHAR_MIN = 0, CHAR_MAX = 255", "como char: 195")}
for flag, (limits, value) in cases.items():
with self.subTest(flag=flag):
target = BUILD / f"char_sign{flag}"
self.assertEqual(compile_c("char_sign.c", target, flag).returncode, 0)
result = subprocess.run([str(target)], input="ñ".encode(), capture_output=True).stdout.decode()
self.assertIn(limits, result)
self.assertIn(value, result)
self.assertIn("como unsigned char: 195", result)
def test_read_bytes(self):
self.assertEqual(out("read_bytes", "año"), "scanf leyó 4 byte(s)\n61 c3 b1 6f\n")
def test_utf8_two_bytes_matches_python(self):
for code in (128, 193, 201, 205, 209, 211, 218, 225, 233, 237, 241, 243, 250, 2047):
with self.subTest(code=code):
first, second = chr(code).encode("utf-8")
self.assertEqual(out("utf8_two_bytes", f"{code}\n"),
f"scanf leyó 1 dato(s)\nbytes: {first:x} {second:x}\n"
f"carácter: {chr(code)}\n")
def test_utf8_table(self):
table = {"A": "41", "n": "6e", "ñ": "c3b1", "€": "e282ac", "😀": "f09f9880"}
for char, encoded in table.items():
with self.subTest(char=char):
self.assertEqual(char.encode("utf-8").hex(), encoded)
self.assertEqual((ord("ñ"), ord("€"), ord("😀")), (0xF1, 0x20AC, 0x1F600))
def test_xxd(self):
result = subprocess.run(["xxd"], input="año\n".encode(), capture_output=True, text=False)
self.assertEqual(result.stdout.decode(), "00000000: 61c3 b16f 0a a..o.\n")
def test_five_characters_seven_bytes(self):
self.assertEqual((len("ñandú"), len("ñandú".encode())), (5, 7))
def test_mojibake(self):
self.assertEqual("ñ".encode().decode("latin-1"), "ñ")
def test_enye_constant_warns(self):
target = BUILD / "char_enye"
result = compile_c("bad/char_enye.c", target)
self.assertRegex(result.stderr, re.compile(r"bad/char_enye\.c:5:14: warning: multi-character character constant"))
self.assertIn("changes value from ‘50097’", result.stderr)
if __name__ == "__main__":
unittest.main()"""Pruebas del laboratorio 3. Corren sobre lab/ con `make test-lab`, y sobre solution/
dentro de `make test`, si esa carpeta existe. La actividad 5 (Git) no se prueba aquí:
se revisa en el laboratorio."""
import os
import re
import subprocess
import unittest
from pathlib import Path
HERE = Path(__file__).resolve().parent
LAB_DIR = os.environ.get("LAB_DIR", "solution")
SOURCE = HERE / LAB_DIR
BIN = HERE / "build" / LAB_DIR
def run(name, stdin=""):
return subprocess.run([str(BIN / name)], input=stdin.encode(), capture_output=True, timeout=20)
def answers():
values = {}
for line in (SOURCE / "answers.txt").read_text(encoding="utf-8").splitlines():
if "=" in line and not line.startswith("#"):
key, value = line.split("=", 1)
# Se aceptan mayúsculas, espacios y el prefijo 0x: c3 b1, C3B1, 0xca.
values[key.strip()] = value.lower().replace(" ", "").replace("0x", "")
return values
class Activity1(unittest.TestCase):
def test_by_hand(self):
self.assertEqual(answers().get("binario_202"), "11001010")
self.assertEqual(answers().get("hexadecimal_202"), "ca")
def test_program_uses_percent_x(self):
self.assertRegex((SOURCE / "hex_202.c").read_text(encoding="utf-8"), r"%[0-9]*[xX]")
self.assertEqual(run("hex_202").stdout.decode().strip().lower(), "ca")
class Activity2(unittest.TestCase):
def test_normal_value(self):
lines = run("int_overflow", "41\n").stdout.decode().strip().splitlines()
self.assertTrue(lines, "el programa no escribió nada")
self.assertEqual(lines[-1], "42")
def test_overflow_message_and_line(self):
stderr = run("int_overflow", "2147483647\n").stderr.decode()
found = re.search(r"int_overflow\.c:(\d+):\d+: runtime error: signed integer overflow", stderr)
self.assertIsNotNone(found, "no apareció el mensaje de overflow")
self.assertEqual(answers().get("linea_overflow"), found.group(1))
class Activity3(unittest.TestCase):
def test_twenty_decimals(self):
self.assertIn("0.30000000000000004441", run("float_print").stdout.decode())
class Activity4(unittest.TestCase):
def test_year_file(self):
path = SOURCE / "year.txt"
self.assertTrue(path.exists(), f"falta crear {LAB_DIR}/year.txt")
data = path.read_bytes()
self.assertIn(data, (b"a\xc3\xb1o\n", b"a\xc3\xb1o"), "year.txt debe contener año, en UTF-8")
self.assertEqual(answers().get("bytes_year"), str(len(data)))
def test_enye_bytes(self):
self.assertEqual(answers().get("bytes_enye"), "c3b1")
if __name__ == "__main__":
unittest.main()Laboratorio
Archivos de partida del laboratorio de la semana.
# Laboratorio 3: completen cada línea después del signo =.
# Primero háganlo a mano y luego compruébenlo con lo que escriben sus programas.
# Actividad 1: 202 en binario (8 bits) y en hexadecimal (2 dígitos).
binario_202 =
hexadecimal_202 =
# Actividad 2: número de línea de int_overflow.c que indica el mensaje runtime error.
linea_overflow =
# Actividad 4: tamaño en bytes de year.txt y los dos bytes de la ñ en hexadecimal.
bytes_year =
bytes_enye =// Actividad 3: escriban 0.1 + 0.2 con 20 decimales.
#include <stdio.h>
int main(void) {
// Completen aquí. Guarden la suma en un double y usen %.20f.
return 0;
}// Actividad 1: escriban 202 en hexadecimal con printf y %x.
#include <stdio.h>
int main(void) {
// Completen aquí. La salida debe ser una sola línea, con el número en hexadecimal.
return 0;
}// Actividad 2: lean un int con scanf, súmenle 1 y escriban el resultado.
#include <stdio.h>
int main(void) {
// Completen aquí. Con la entrada 41, la última línea de la salida debe ser 42.
return 0;
}Compilación
Cómo se compilan y ejecutan los ejemplos.
# Semana 3: bits y representación de datos. Se usa dentro del entorno del curso.
#
# make compila los programas de la clase en build/
# make lab compila su laboratorio (lab/*.c) en build/lab/
# make test corre las pruebas de los ejemplos y, si existe solution/, las del laboratorio
# make test-lab prueba su laboratorio (lab/); falla hasta que lo terminen
# make clean borra lo generado
CC = gcc
CFLAGS = -Wall -Wextra -std=c17 -g -fsanitize=address,undefined
LDLIBS = -lm
BUILD = build
PROGRAMS = to_binary from_binary bases sizes twos_complement overflow unsigned_wrap \
float_sum fraction_to_binary float_limits compare_doubles money char_codes char_sign \
read_bytes utf8_two_bytes
LAB_PROGRAMS = hex_202 int_overflow float_print
.PHONY: all lab test test-lab clean
all: $(PROGRAMS:%=$(BUILD)/%)
$(BUILD)/%: %.c | $(BUILD)
$(CC) $(CFLAGS) -o $@ $< $(LDLIBS)
$(BUILD)/lab/%: lab/%.c | $(BUILD)/lab
$(CC) $(CFLAGS) -o $@ $< $(LDLIBS)
$(BUILD)/solution/%: solution/%.c | $(BUILD)/solution
$(CC) $(CFLAGS) -o $@ $< $(LDLIBS)
$(BUILD) $(BUILD)/lab $(BUILD)/solution:
mkdir -p $@
lab: $(LAB_PROGRAMS:%=$(BUILD)/lab/%)
# Si existe solution/, también se comprueba la solución del laboratorio.
test: all
python3 -m unittest -v test_examples
@if [ -d solution ]; then \
$(MAKE) --no-print-directory $(LAB_PROGRAMS:%=$(BUILD)/solution/%) && \
LAB_DIR=solution python3 -m unittest -v test_lab; fi
test-lab: lab
LAB_DIR=lab python3 -m unittest -v test_lab
clean:
rm -rf $(BUILD) __pycache__