11.6. Как подсчитывается CRC32?

Ниже приведены тексты программы для подсчета CRC32 заданного файла.

    ----------------------------------------------- crc.h
    typedef unsigned char  uchar; /*  8 bits or more */
    typedef unsigned int   uint; /* 16 - 32 bits or more */
    typedef unsigned short ushort; /* 16 bits or more */
    typedef unsigned long  ulong; /* 32 bits or more */
    typedef ulong UCRC; /* CRC-32 */
    #define CRC_MASK    0xFFFFFFFFUL
    extern UCRC crc;

    ----------------------------------------------- crc.c
    #include <stdio.h>
    #include "crc.h"
    #include <stdlib.h>

    /* Global variables */

    UCRC   crc;
    FILE   *fp;

    #define BUFFERSIZE  32768U
    #define CRCPOLY     0xEDB88320UL
    /* 1110 1101 1001 1000 1000 0011 0010 0000 */
    #define UPDATE_CRC(crc, c)  \
        crc = crctable[(uchar)crc ^ (uchar)(c)] ^ (crc >> 8)
    static UCRC   crctable[256];

    static void make_crctable( void ) {
        uint i, j;
        UCRC r;

        for (i = 0; i <= 255; i++) {
        r = i;
        for (j = 8; j > 0; j--) {
            if (r & 1)
            r = (r >> 1) ^ CRCPOLY;
            else
            r >>= 1;
        }
        crctable[i] = r;
        /*
        printf( "%08lx  ", crctable[i] );
        if( i % 8 == 7 )
           printf( "\n" );
        */
        }
    }

    int main( int argc, char *argv[] ) {
      size_t len;
      char *buffer, *sav;

        if ( argc != 2 ) {
        printf("Usage: CRC32 <File_Name>\n" );
        return 1;
        }
        if ( ( fp = fopen( argv[1], "rb" ) ) == NULL ) exit(1);

        make_crctable();
        crc = CRC_MASK;
        buffer = (char *) calloc( BUFFERSIZE,1 );
      sav = buffer;
      while ( ( len = fread(buffer,1,BUFFERSIZE,fp) ) > 0 ) {
        while ( len-- ) UPDATE_CRC( crc, *buffer++ );
        buffer = sav;
      }
      free(buffer);
      len = (unsigned int)(crc>>16);
      printf( "File = %13s CRC32 = %04x%04x\n", argv[1], (int)~len, (int)~crc );

      fclose( fp );
      flushall();
        return 0;
    }