C语言 按位移位运算符和文件指针

xqkwcwgp  于 2022-12-17  发布在  其他
关注(0)|答案(1)|浏览(127)

你能解释一下为什么每当我调用这个函数时,文件指针会移位吗?这段代码是如何工作的?...

static long fget32le(FILE* fp)
{
    long answer;
    answer = fgetc(fp);
    answer |= (fgetc(fp) << 8);
    answer |= (fgetc(fp) << 16);
    answer |= (fgetc(fp) << 24);
    /* check for negative */
    if (answer & 0x80000000)
        answer |= ((-1) << 31);
    return answer;
}

...
自己试试这个简单的例子,试着注解fget32le(file)函数并检查fread的行为,然后试着在fget32le(file)启用的情况下运行相同的函数:当Fread在64位偏移之后开始阅读时,Fread的行为改变。

pBitmap loadBmp(const char* fileIn) 
{
    FILE* file = fopen(fileIn, "rb");
    if (!file) {
        printf("Unable to load file\n");
        return NULL;
    }

    fget32le(file);
    fget32le(file);

    unsigned char bmpHeader[54];
    fread(bmpHeader, 1, 54, file);

    if (bmpHeader[0] != 'B' || bmpHeader[1] != 'M') {
        printf("The loaded file is not a valid Bitmap\n");
        fclose(file);
        return NULL;
    }

    int width = *(int*)&bmpHeader[18];
    int height = *(int*)&bmpHeader[22];
67up9zun

67up9zun1#

文件指针没有被移动,只有字符被读取。
负面检查应该是

if(answer < 0)

此行调用未定义的行为

answer |= ((-1) << 31);

E1〈〈E2的结果是E1左移E2比特位置;如果E1是无符号类型,则结果值为E1 × 2 E2,比结果类型中可表示的最大值再模1。如果E1是有符号类型,且值为非负值,且E1 × 2 E2可在结果类型中表示,则这就是结果值;否则,行为未定义。
文件是:0x 0000029 a82642 fe 0,然后它变成0x 0000029 a8264 e924,然后变成0x 0000029 a8264 e928。这就是我问你的原因。
这个函数不能改变传递的指针,因为它是fget32le函数的本地指针。您的观察是错误的,或者是其他东西(您没有显示给我们)正在改变指针。
自己试试这个简单的例子,试着注解fget 32 le(file)函数并检查fread的行为,然后试着在fget 32 le(file)启用的情况下运行相同的函数:当Fread在64位偏移之后开始阅读时,Fread的行为改变。
因为您已经读取了8个字节,所以fread将从第9个字节开始读取文件。
如果要从头开始,您需要:

fget32le(file);
    fget32le(file);

    /* ... */
    fseek(file, 0, SEEK_SET);

    fread(bmpHeader, 1, 54, file);

相关问题