I've been working on a small program to dump the hex values of a file, similar to od
or hexdump
, and I've ran into an issue when printing the values. For certain hex values, mostly ones with alphabetical characters as their second digit, it prints with 6 extra f digits before printing the actual number, instead of just printing a 2-width value like I had specified. I have confirmed that the values themselves are not unexpected in any way, it's the printing that's messing it up.
Code:
int main(int argc, char* argv[]) {
FILE* dataFile = fopen(argv[1], "rb");
int byteCount = 0;
char currentByte = fgetc(dataFile);
while (currentByte != EOF) {
printf("d", byteCount);
do {
//print as hex
printf(" x ", currentByte);
//set up for next loop
currentByte = fgetc(dataFile);
byteCount ;
} while (currentByte != EOF && (byteCount) % 16 != 0);
printf("\n");
}
printf("d\n", byteCount);
}
Output:
00000000 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
00000016 03 00 3e 00 01 00 00 00 10 6b 00 00 00 00 00 00
00000032 40 00 00 00 00 00 00 00 08 23 02 00 00 00 00 00
00000048 00 00 00 00 40 00 38 00 0d 00 40 00 1f 00 1e 00
00000064 06 00 00 00 04 00 00 00 40 00 00 00 00 00 00 00
00000080 40 00 00 00 00 00 00 00 40 00 00 00 00 00 00 00
00000096 ffffffd8 02 00 00 00 00 00 00 ffffffd8 02 00 00 00 00 00 00
00000112 08 00 00 00 00 00 00 00 03 00 00 00 04 00 00 00
00000128 18 03 00 00 00 00 00 00 18 03 00 00 00 00 00 00
00000144 18 03 00 00 00 00 00 00 1c 00 00 00 00 00 00 00
00000160 1c 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00
00000176 01 00 00 00 04 00 00 00 00 00 00 00 00 00 00 00
00000192 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00000208 fffffff8 34 00 00 00 00 00 00 fffffff8 34 00 00 00 00 00 00
Does anyone know what's going on here?
CodePudding user response:
There are several problems here.
char
is entirely unsuitable to hold raw binary data, because it has implementation-defined signedness and it often a signed type, see Is char signed or unsigned by default?. In factchar
should only ever be used for text strings. Instead, you would normally useuint8_t
. However... :- The
EOF
constant is of typeint
, so if you intend to compare something againstEOF
, it must be typeint
.fgetc
is guaranteed to return characters as if they wereunsigned char
but converted toint
- as it happens,int
is large enough to hold all values of anunsigned char
soint
can be used here. %x
specifier forprintf
expects anunsigned int
.
Fixes:
char currentByte
->int currentByte
printf(" x ", currentByte);
->printf(" x ", (unsigned int)currentByte);
.- You must always check if
fopen
was successful and alsofclose
the file pointer when done. Also note that callingfopen
directly on argv with no input sanitation is not acceptable in a professional program. You don't even know ifargv[1]
exists - the program needs a whole lot more error handling overall.