Language
C
Compiler
gcc 13.2.0
Options
Warnings
Compiler Default
no pedantic
#include <stdio.h>
#include <string.h>
#include <inttypes.h>
// 成功時1、失敗時0を返す
int crc32_bytes(uint8_t bytes_out[], int num_bytes, uint32_t status_before, uint32_t status_after) {
static const uint32_t MAGIC = UINT32_C(0xEDB88320);
uint32_t status = status_after;
if (num_bytes < 0 || 4 < num_bytes) return 0;
if (num_bytes == 0) return status_before == status_after;
// シフトとマジックナンバーのXORの処理を逆回しする
for (int i = 0; i < 8 * num_bytes; i++) {
uint32_t msb = status & UINT32_C(0x80000000);
if (msb) {
status ^= MAGIC;
status <<= 1;
status |= 1;
} else {
status <<= 1;
}
}
// 更新前の状態をXORする
status ^= status_before;
// 上位が0になっていることを確認する
if (num_bytes < 4 && (status & (UINT32_C(0xFFFFFFFF) << 8 * num_bytes))) return 0;
// バイト列を取り出す
for (int i = 0; i < num_bytes; i++) {
bytes_out[i] = status >> 8 * i;
}
return 1;
}
void test(uint32_t status_before, uint32_t status_after) {
printf("0x%08" PRIx32 " -> 0x%08" PRIx32 "\n", status_before, status_after);
for (int size = 1; size <= 4; size++) {
uint8_t data[4];
if (crc32_bytes(data, size, status_before, status_after)) {
for (int i = 0; i < size; i++) {
if (i > 0) putchar(' ');
printf("%02x", (unsigned int)data[i]);
}
putchar('\n');
}
}
}
int main(void) {
test(UINT32_C(0x992BAC53), UINT32_C(0x639F4775));
test(UINT32_C(0x992BAC53), UINT32_C(0x51BD9F7D));
test(UINT32_C(0x22FDE946), UINT32_C(0x51BD9F7D));
test(UINT32_C(0xFFFFFFFF), UINT32_C(0x51BD9F7D));
return 0;
}
$ gcc prog.c -Wall -Wextra
0x992bac53 -> 0x639f4775
4e
8a 6a fb 27
0x992bac53 -> 0x51bd9f7d
4e 44
e5 16 9a 22
0x22fde946 -> 0x51bd9f7d
45 4e 44
f0 53 4c 99
0xffffffff -> 0x51bd9f7d
49 45 4e 44
Exit Code:
0