结合学校的crc校验的基础知识,直接使用zlib/crc32函数应该一点门槛都没有。。下面是zlib.h中自带的示例和讲解:
Update a running CRC-32 with the bytes buf[0..len-1] and return the updated CRC-32. If buf is NULL, this function returns the required initial value for the for the crc. Pre- and post-conditioning (one's complement) is performed within this function so it shouldn't be done by the application. Usage example: uLong crc = crc32(0L, Z_NULL, 0); while (read_buffer(buffer, length) != EOF) { crc = crc32(crc, buffer, length); } if (crc != original_crc) error();
crc校验支持两种方式:
// g++ crc_test.cpp -o exec_crc_test -L /usr/lib64/ -lz #include <stdio.h> #include <stdlib.h> #include <zlib.h> #include <string.h> void CRC_Partial_Check_Test(); template<class Type> void CRC_Full_Check_Test(); // crc32 use uLong, typedef unsigned long uLong; typedef uLong ulong_t; // 32bit, 64bit. int main() { CRC_Partial_Check_Test(); CRC_Full_Check_Test<unsigned int>(); CRC_Full_Check_Test<ulong_t>(); printf("any key pressed to exit...\n"); getchar(); return 0; } typedef union { ulong_t val; unsigned char buf[sizeof(ulong_t)]; } trans_un_t; void CRC_Partial_Check_Test() { printf("=============================>>CRC_Partial_ChecK_Test\n"); char* buffer = "hello world, i am renyafei"; int buffer_sz = strlen(buffer); { FILE* fp = fopen("crc.dat", "wb"); fwrite(buffer, 1, buffer_sz, fp); ulong_t crc_code = crc32(0, (const Bytef*)buffer, buffer_sz); printf("crc_code : %lu\n", crc_code); fwrite(&crc_code, 1, sizeof(ulong_t), fp); fflush(fp); fclose(fp); } { FILE* fp = fopen("crc.dat", "rb"); unsigned char content[1024] = {0}; int read_bytes = fread(content, 1, buffer_sz+sizeof(ulong_t), fp); ulong_t crc_code = 0; { // get crc code unsigned char* pch = content + buffer_sz; trans_un_t trans; for(int k=0; k<sizeof(ulong_t); k++) { printf("%d ", pch[k]); trans.buf[k] = pch[k]; } printf("\n"); printf("crc_code : %lu\n", trans.val); crc_code = trans.val; } if ( crc32(0, content, buffer_sz) != crc_code ) { printf("ERROR content.\n"); } else { printf("Good Content.\n"); } fclose(fp); } } template<class Type> void CRC_Full_Check_Test() { printf("=============================>>CRC_Full_ChecK_Test\n"); char* buffer = "hello world, i am renyafei"; int buffer_sz = strlen(buffer); typedef Type dest_t; { FILE* fp = fopen("crc.dat", "wb"); fwrite(buffer, 1, buffer_sz, fp); ulong_t crc = crc32(0, (const Bytef*)buffer, buffer_sz); dest_t rever_crc = (dest_t)~crc; printf("crc = %lu, reverse_crc_code : %lu\n", crc, rever_crc); fwrite(&rever_crc, 1, sizeof(dest_t), fp); fflush(fp); fclose(fp); } { FILE* fp = fopen("crc.dat", "rb"); unsigned char content[1024] = {0}; int read_bytes = fread(content, 1, buffer_sz+sizeof(dest_t), fp); { // get crc code unsigned char* pch = content + buffer_sz; trans_un_t trans; memcpy(trans.buf, pch, sizeof(ulong_t)); printf("reverse_crc_code : %lu\n", trans.val); } ulong_t res = crc32(0, content, read_bytes); printf("res = %lu\n", res); if ( res != 0xFFFFFFFF && res != 0xFFFFFFFFFFFFFFFF ) { printf("ERROR content.\n"); } else { printf("Good Content.\n"); } fclose(fp); } }CRC_Partial_Check_Test为上文中的方式1,CRC_Full_Check_Test为方式2。
=============================>>CRC_Partial_ChecK_Test crc_code : 4232166920 8 190 65 252 0 0 0 0 crc_code : 4232166920 Good Content. =============================>>CRC_Full_ChecK_Test crc = 4232166920, reverse_crc_code : 62800375 reverse_crc_code : 62800375 res = 4294967295 Good Content. =============================>>CRC_Full_ChecK_Test crc = 4232166920, reverse_crc_code : 18446744069477384695 reverse_crc_code : 18446744069477384695 res = 558161692 ERROR content.
ulong_t code = 0xfc << 24; unsigned int ui_code = 0xfc << 24; printf("ulong_res = %lu, uint_res = %lu\n", code, ui_code); code = 0xfc << 8; ui_code = 0xfc << 8; printf("ulong_res = %lu, uint_res = %lu\n", code, ui_code);输出结果如下:
ulong_res = 18446744073642442752, uint_res = 4227858432 ulong_res = 64512, uint_res = 64512第一行uLong_res输出结果很奇怪。通过dump_val_hex函数输出一个数字的16进制形式:
template<class Type> void dump_val_hex_recur(Type val) { if (val == 0) { return; } unsigned char byte = val & 0xFF; dump_val_hex_recur(val >> 8); printf("%02x ", byte); } template <class Type> void dump_val_hex(Type val) // 0xfc000000 => printf : fc 00 00 00 { if (val == 0) { printf("%02x\n", 0); return; } dump_val_hex_recur(val); printf("\n"); }
18446744073642442752对应的16进制形式为ff ff ff ff fc 00 00 00 。诡异的移位结果,居然高位被1填充。但是0xfc << 8 的结果确实高位被0填充。
在vs2013上面做类似的尝试,也有同样的结果:
unsigned long long val = 0xfc << 24; 00B332D8 mov dword ptr [val],0FC000000h 00B332DF mov dword ptr [ebp-68h],0FFFFFFFFh
val = 0xfc << 8; 009C32F6 mov dword ptr [val],0FC00h 009C32FD mov dword ptr [ebp-68h],0结果非常诡异,暂时想不通原因,总之小心为好。