- Passing a NULLpointer tofclose()invokes undefined behaviour.¹
As the program exits on fopen() failure, we could have a function like so:
static void open_sesame (const char *restrict stream, const char *restrict mode) 
{
    if (!fopen (stream, mode)) {
        perror ("fopen():");
        exit (EXIT_FAILURE);
    }
}
Now your code simplifies to:
FILE *fp1 = open_sesame ("file1.bin", "w+b");
FILE *fp2 = open_sesame ("file2.bin", "r+b");
...
fclose (fp1);
fclose (fp2);
- The data buffered by printf()is flushed whenfflush (stdout)is called, or when the program terminates. Ifstdoutis line-buffered (which is usually the case when the stream is connected to a terminal/console), then the stream will also be flushed when a newline character is encountered. But since the program invokes undefined behaviour, no assumption about the continuation of the execution of the program can be made.
Add a newline in the call to printf(), or call fflush (stdout);.
Footnote:
The standard doesn't define the behaviour, so this rule applies:
Each of the following statements applies unless explicitly stated
otherwise in the detailed descriptions that follow: If an argument to
a function has an invalid value (such as a value outside the domain of
the function, or a pointer outside the address space of the program,
or a null pointer, or a pointer to non-modifiable storage when the
corresponding parameter is not const-qualified) or a type (after
promotion) not expected by a function with variable number of
arguments, the behavior is undefined. — 7.1.4p1 C18 standard.