Home > Software engineering >  Bitwise shift operator and file pointer
Bitwise shift operator and file pointer

Time:12-15

Can you please explain why, whenever I call this function, the file pointer is shifted? How does this piece of code work? ...

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;
}

...

Try this simple example by your own. Try to comment fget32le(file) functions and check the behavior of fread. Then try to run the same with fget32le(file) enabled: the behaviour of fread changes as it starts reading after a 64 bits offset.

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];

CodePudding user response:

The file pointer is not being shifted, only the character read.

The negative check should be

if(answer < 0)

This line invokes undefined behavior

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

The result of E1 << E2 is E1 left-shifted E2 bit positions; vacated bits are filled with zeros. If E1 has an unsigned type, the value of the result is E1 × 2E2, reduced modulo one more than the maximum value representable in the result type. If E1 has a signed type and nonnegative value, and E1 × 2E2 is representable in the result type, then that is the resulting value; otherwise, the behavior is undefined.

file is: 0x0000029a82642fe0, then it becomes 0x0000029a8264e924 and then 0x0000029a8264e928. This is why I'm asking.

This function cannot change the pointer passed as it is local to the fget32le function. Your observation is wrong or something else (which you did not show us) is changing the pointer.

Try this simple example by your own. Try to comment fget32le(file) functions and check the behavior of fread. Then try to run the same with fget32le(file) enabled: the behaviour of fread changes as it starts reading after a 64 bits offset.

It is because you have already read 8 bytes, so the file will be read by fread from the 9th byte.

If you want to start again from the beginning you need to :

    fget32le(file);
    fget32le(file);

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

    fread(bmpHeader, 1, 54, file);
  • Related