Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Bitwise shift operator and file pointer

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.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

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

>Solution :

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);
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading