Let's say you have a binary file. Let's say you want to read 8 bytes from the
file.
FILE *fp = fopen("a", "rb");
if(fp == NULL)
return;
unsigned char bytes[8];
if(fread(bytes, sizeof bytes / sizeof *bytes, 1, fp) != 1)
{
fprintf(stderr, "could not read 8 bytes\n");
return;
}
// printing the bytes:
for(size_t i = 0; i < sizeof bytes / sizeof *bytes; ++i)
printf("%02X ", bytes[i]);
puts("");
fclose(fp);
I run this code reading the compiled binary (filename is a) of this same code, the first 8
bytes are:
7F 45 4C 46 02 01 01 00
As you can see there are bytes that have no representation and if I would print
that as a string, this would be the result:

which is less helpful, here I was lucky that there were at least printable
integers.
And if you want to have also the printable characters printed as as well (like hex editors
do):
size_t n;
// yes I swapped the number of items and the number of bytes here
// for reading the whole file
while((n = fread(bytes, 1, sizeof bytes / sizeof *bytes, fp)))
{
size_t i;
for(i = 0; i < n; ++i)
printf("%02X ", bytes[i]);
// if less than array size bytes read, to align output
printf("%*s", (int) ((sizeof bytes / sizeof *bytes) - i)*3, "");
printf("%10s |", "");
for(i = 0; i < n; ++i)
{
if(isprint(bytes[i]))
printf("%c", bytes[i]);
else
printf(".");
}
// same here as above
printf("%*s", (int) ((sizeof bytes / sizeof *bytes) - i), "");
puts("|");
}
This outputs:
7F 45 4C 46 02 01 01 00 |.ELF....|
00 00 00 00 00 00 00 00 |........|
03 00 3E 00 01 00 00 00 |..>.....|
A0 07 00 00 00 00 00 00 |........|
40 00 00 00 00 00 00 00 |@.......|
F0 23 00 00 00 00 00 00 |.#......|
00 00 00 00 40 00 38 00 |[email protected].|
09 00 40 00 23 00 22 00 |..@.#.".|
...
00 6C 69 62 63 2E 73 6F |.libc.so|
2E 36 00 66 6F 70 65 6E |.6.fopen|
00 70 75 74 73 00 5F 5F |.puts.__|
73 74 61 63 6B 5F 63 68 |stack_ch|
6B 5F 66 61 69 6C 00 70 |k_fail.p|
75 74 63 68 61 72 00 70 |utchar.p|
72 69 6E 74 66 00 66 63 |rintf.fc|
6C 6F 73 65 00 5F 5F 63 |lose.__c|
74 79 70 65 5F 62 5F 6C |type_b_l|
...
39 01 00 00 00 00 00 00 |9.......|
00 00 00 00 00 00 00 00 |........|
01 00 00 00 00 00 00 00 |........|
00 00 00 00 00 00 00 00 |........|
uint8_tarrays orunsigned chararrays, but do not treat them as strings. Also when you read a binary file, many bytes are just not printable and if you print them, you will get "garbage" on the screen. It's better to print the hex representation of the bytes.printf("%.*s", str_len, str_ptr);fwriteto write arbitrary data to stdout as long as you remember how much data you have (because, again, it's not a string...there's noarbitrarydatalenfunction, and there can't be).printffor that:printf("%02x\n", val);NUL, binary data does not have to fit that format at all.