user3646905
user3646905

Reputation:

Read a file in binary mode with c

I have an executable file called re.exe, I want to read its content in the binary form and then show that content in the console. I write the following code but it doesn't show the content of the binary file in the console. What's the problem?

#include <stdio.h>
#include <ctype.h>

void readFile(const char *fileName) {
    FILE *file;
    file = fopen(fileName, "rb");
    if (file != NULL) {
        char ch;
        while ((ch = fgetc(file)) != EOF) {
            if (isprint(ch)) {
                printf("%x", ch);
            }
            else {
                printf("%02x", ch);
                if (ch == '\n') {
                    fputs("\n", stdout);
                }
            }
        }
     fclose(file);
    }
}

int main() {

    readFile("re.exe");

    return 0x0;
}

Upvotes: 2

Views: 997

Answers (1)

s7amuser
s7amuser

Reputation: 857

The problem is the implicit casting of the return value of fgetc from int to char.

Since EOF is defined as (-1) (at least in glibc), the returned char (which is by default signed in GCC) is converted to an int (with sign extension) as specified in section 6.3.1.8 of the C99 standard:

If both operands have the same type, then no further conversion is needed.

Otherwise, if both operands have signed integer types or both have unsigned integer types, the operand with the type of lesser integer conversion rank is converted to the type of the operand with greater rank.

As a result, the character 0xff is converted to 0xffffffff and is actually equal to the value of EOF which causes the loop to end prematurely before reading all the file.

In addition, when printing the character with printf("%x", ch) or printf("%02x", ch), the character is again converted to an int (see here) and thus you can see for example the output 0xffffff90 for the character 0x90.

In summary, the solution is defining ch to be an int instead of a char.

Upvotes: 3

Related Questions