我有代码,必须将0x3B9ACA02432543更改为某个值,以使此代码的结果等于校验和结果.

我try 将其更改为检验和默认值0x04C11DB7,但结果值不同

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char **argv) {
    if (argc != 2) {
        fprintf(stderr, "usage: %s <file>\n", argv[0]);
        exit(EXIT_FAILURE);
    } else {
        FILE *f = NULL;
        int c;

        f = fopen(argv[1], "rb");
        if (f == NULL)
            perror("fopen()");
        else {
            int size = 0;
            int crc;
            int c;
            int i, j;
            int crc_table[256];
            for (i = 0; i < 256; i++) {
                crc = i;
                for (j = 0; j < 8; j++)
                    crc = crc & 1 ? (crc >> 1) ^ 0x3B9ACA02432543 : crc >> 1;

                crc_table[i] = crc;
            }
            crc = 0;

            while ((c = fgetc(f)) != EOF) {
                ++size;
                crc = crc_table[(crc ^ c) & 0xFF] ^ (crc >> 8);
            }
            crc ^= 0xFFFFFFFFUL;
            printf("%u\n", crc);
        }

    }

    return 0;

}

推荐答案

你没有说你使用的是什么操作系统或cksum的来源.它在不同的系统上是不同的.在我的MacOS(BSD派生的)系统上,cksum -o 3将计算您可能指的标准CRC-32.

在这种情况下,您需要将初始CRC设置为0xffffffff,并且需要使用多项式0x04c11db7的反射,即0xedb88320.此外,您应该使用长度至少为32位的类型.long是,int不是.您还需要在CRC计算中使用无符号类型,以便向下移位不会复制高位.

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char **argv) {
    if (argc != 2) {
        fprintf(stderr, "usage: %s <file>\n", argv[0]);
        exit(EXIT_FAILURE);
    }
    else {
        FILE *f = NULL;
        f = fopen(argv[1], "rb");
        if (f == NULL)
            perror("fopen()");
        else {
            unsigned long crc;
            int c;
            int i, j;
            unsigned long crc_table[256];
            for (i = 0; i < 256; i++) {
                crc = i;
                for (j = 0; j < 8; j++)
                    crc = crc & 1 ? (crc >> 1) ^ 0xedb88320 : crc >> 1;
                crc_table[i] = crc;
            }
            crc = 0xffffffff;
            while ((c = fgetc(f)) != EOF)
                crc = crc_table[(crc ^ c) & 0xff] ^ (crc >> 8);
            crc ^= 0xffffffff;
            printf("%lu\n", crc);
        }
    }
    return 0;
}

POSIX cksum是另一个变种.它使用非反射CRC,从0而不是0xffffffff开始,并将数据长度附加到用于CRC计算的数据.该长度采用小端顺序,表示该长度所需的字节数最少.为方便起见,我使用了C99提供的显式大小的整数:

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>

int main(int argc, char **argv) {
    if (argc != 2) {
        fprintf(stderr, "usage: %s <file>\n", argv[0]);
        exit(EXIT_FAILURE);
    }
    else {
        FILE *f = NULL;
        f = fopen(argv[1], "rb");
        if (f == NULL)
            perror("fopen()");
        else {
            uint32_t crc;
            uint32_t crc_table[256];
            for (uint32_t i = 0; i < 256; i++) {
                crc = i << 24;
                for (int j = 0; j < 8; j++)
                    crc = crc & 0x80000000 ? (crc << 1) ^ 0x04c11db7 : crc << 1;
                crc_table[i] = crc;
            }
            uint64_t size = 0;
            crc = 0;
            int c;
            while ((c = fgetc(f)) != EOF) {
                size++;
                crc = crc_table[(crc >> 24) ^ c] ^ (crc << 8);
            }
            while (size) {
                crc = crc_table[(crc >> 24) ^ (size & 0xff)] ^ (crc << 8);
                size >>= 8;
            }
            crc = ~crc;
            printf("%lu\n", (unsigned long)crc);
        }
    }
    return 0;
}

C++相关问答推荐

使用sd-设备列举设备导致seg错误

如何将匿名VLA分配给指针?

C限制限定符是否可以通过指针传递?

C sscanf没有捕获第二个参数

通过MQTT/蚊子发送大文件—限制在4MB

如果实际的syscall是CLONE(),那么为什么strace接受fork()呢?

当多个线程在C中写入相同的文件描述符时,如何防止争用情况?

将指针作为参数传递给函数

如何在c++中包装返回空*的函数

预先分配虚拟地址空间的区域

如何识别Linux中USB集线器(根)和连接到集线器(根设备)的设备(子设备)?

每次除以或乘以整数都会得到0.0000

C23标准是否向后兼容?

即使我在C++中空闲,也肯定会丢失内存

意外的C并集结果

Tcl_GetDoubleFromObj在列表的迭代中是一个缺点

std::malloc/calloc/realloc/free 与纯 C 的 malloc/calloc/realloc/free 有什么不同

为什么 Linux 共享库 .so 在内存中可能比在磁盘上大?

为什么实现文件中的自由函数默认没有内部链接?

C11 嵌套泛型