结合学校的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
#include
#include
#include
void CRC_Partial_Check_Test();
template 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();
CRC_Full_Check_Test();
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
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 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 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
结果非常诡异,暂时想不通原因,总之小心为好。