CRC является аддитивным в математическом смысле, так как хэш CRC - это просто остаток от простого переноса всех данных (рассматриваемых как гигантское целое число), разделенных на полиномиальную константу. Используя ваш пример, это похоже на подобные вещи:
7 мод 5 = 2
6 мод 5 = 1
(7 мод 5) + (6 мод 5) = 3
(7 + 6) мод 5 = 3
В этой аналогии «5» является нашим полиномом CRC.
Вот пример для игры (на основе gcc):
#include <stdio.h>
#include <x86intrin.h>
int main(void)
{
unsigned int crc_a = __builtin_ia32_crc32si( 0, 5);
printf( "crc(5) = %08X\n", crc_a );
unsigned int crc_b = __builtin_ia32_crc32si( 0, 7);
printf( "crc(7) = %08X\n", crc_b );
unsigned int crc_xor = crc_a ^ crc_b;
printf( "crc(5) XOR crc(7) = %08X\n", crc_xor );
unsigned int crc_xor2 = __builtin_ia32_crc32si( 0, 5 ^ 7);
printf( "crc(5 XOR 7) = %08X\n", crc_xor2 );
return 0;
}
Вывод соответствует ожидаемому:
plxc15034> gcc -mcrc32 -Wall -O3 crctest.c
plxc15034> ./a.out
crc(5) = A6679B4B
crc(7) = 1900B8CA
crc(5) XOR crc(7) = BF672381
crc(5 XOR 7) = BF672381
Поскольку этот код использует инструкцию x86 CRC32, он будет работать только на Intel i7 или новее. Встроенная функция принимает текущий хэш CRC в качестве первого параметра, а новые данные накапливаются в качестве второго параметра. Возвращаемое значение - новый запущенный CRC.
Первоначальное значение CRC, равное 0, в приведенном выше коде является критическим. Используя любое другое начальное значение, CRC не является «аддитивным» в практическом смысле, потому что вы фактически выбросили информацию о целом числе, на которое делите. И это именно то, что происходит в вашем примере. Функции CRC никогда не инициализируют это начальное значение CRC равным нулю, но обычно -1. Причина в том, что начальный CRC, равный 0, позволяет любому количеству ведущих 0 в данных просто проваливаться без изменения значения текущего CRC, которое остается равным 0. Таким образом, инициализация CRC в 0 является математически обоснованной, но для практических целей расчета хэш, это последнее, что вы хотели бы.