Modbus

uint16_t crc16modbus(const uint8_t *data, size_t data_len) {
	uint16_t crc = UINT16_C(0xFFFF);
	for (size_t i = 0; i < data_len; ++i) {
		crc ^= (uint16_t)data[i];
		for (uint8_t j = 0; j < 8; ++j) {
			if (crc & 1) {
				crc = (crc >> 1) ^ UINT16_C(0xA001);
			} else {
				crc >>= 1;
			}
		}
	}
	return crc;
}

Castagnoli

uint32_t crc32c(const uint8_t *data, size_t data_len) {
	uint32_t crc = UINT32_C(0xFFFFFFFF);
	for (size_t i = 0; i < data_len; ++i) {
		crc ^= (uint32_t)data[i];
		for (uint8_t j = 0; j < 8; ++j) {
			if (crc & 1) {
				crc = (crc >> 1) ^ UINT32_C(0x82F63B78);
			} else {
				crc >>= 1;
			}
		}
	}
	return crc ^ UINT32_C(0xFFFFFFFF);
}
uint32_t crc32c_x86(const uint8_t *data, size_t data_len) {
	uint64_t crc = UINT64_C(0xFFFFFFFF);
	while (data_len >= 8) {
		uint64_t chunk;
		memcpy(&chunk, data, sizeof(chunk));
		crc = _mm_crc32_u64(crc, chunk);
		data += 8;
		data_len -= 8;
	}
	while (data_len >= 4) {
		uint32_t chunk;
		memcpy(&chunk, data, sizeof(chunk));
		crc = _mm_crc32_u32(crc, chunk);
		data += 4;
		data_len -= 4;
	}
	while (data_len > 0) {
		crc = _mm_crc32_u8(crc, *data);
		data++;
		data_len--;
	}
	return crc ^ UINT32_C(0xFFFFFFFF);
}