networking · intermediate · ~25 min
Bit-by-bit polynomial division — the heart of every CRC.
Compute a CRC-8 checksum over a byte stream, bit by bit. This is the same loop that 1-Wire sensors, USB Power Delivery, and CAN bus frames use.
Implement unsigned char crc8(const unsigned char *data, size_t len) using polynomial 0x07, initial value 0x00, and no final XOR-out.
The algorithm:
crc = 0.len bytes b in data:crc ^= b.crc is set, crc = (crc << 1) ^ 0x07; otherwise crc = crc << 1. Keep crc masked to 8 bits.crc.data: the byte buffer to checksum.len: number of bytes to process.The final CRC-8 value as an unsigned char.
crc8("123456789", 9) -> 0xF4 (canonical CRC-8 check value)
crc8("", 0) -> 0x00
crc8("\x01", 1) -> 0x07
crc8("A", 1) -> 0xC0 ('A' is 0x41)
len == 0) returns 0x00.CRC checksums are everywhere: 1-Wire / I²C / CAN / SMBus all use CRC-8, and TCP/Ethernet use larger CRCs with the same core algorithm. Writing one by hand demystifies what looks like a magic value in protocol specs.
data, the byte buffer; len, the number of bytes to process.
The final CRC-8 value as an unsigned char (poly 0x07, init 0x00, no XOR-out).
No lookup tables; bit-by-bit loop; keep crc masked to 8 bits.
#include <stddef.h>
unsigned char crc8(const unsigned char *data, size_t len) { /* TODO */ return 0; }
Forgetting to mask crc back to 8 bits after the shift. Using the wrong polynomial. Initialising with 0xFF (some CRC-8 variants do; this one uses 0x00).
Empty buffer → 0; single byte; ASCII string "123456789" is the canonical check value (0xF4).
O(8 * len).
Solve this exercise in the browser editor — compile and run against the test harness, no setup required.