How fwrite "works"
You can start by looking at the fwrite manual. It's signature is:
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
So, let's break down each argument:
ptr is the source location of your data (where you data is).
size is the size of each element of data. fwrite writes in chunks of size bytes each time it loops.
nmemb is the number of loops fwrite will perform.
stream is the file descriptor (FILE*) of your output file.
So, with that in mind, imagine this:
// our dear string
char *str = "#SO";
// open a bogus file to write
FILE *fp = fopen(foo, "wb");
// call fwrite and store returned value
size_t ret = fwrite(str, 3, 1, fp);
This code will do the following (other than not compiling): Starting at location pointed by str, it will write 3 bytes in the file pointed by fp 1 time. However, if you did it like this:
size_t ret = fwrite(str, 1, 3, fp);
That would tell fwrite to write 1 byte to the file for every iteration it does, and it would do 3 iterations.
In your case, you read a character from f1 and want to write it to f3. Therefore, you should have something like this:
ret = fwrite(&c, sizeof(c), 1, f3);
That will read the binary character from f1 and copy it to f3.
Note that this might not be (and probably is not) the way fwrite works internally. What I presented here is the mental model I use to remember its arguments. If you actually read fwrite source code, you may find a very different implementation.
Example
So, a simple program to copy from f1 to f2 is:
#include <stdio.h>
int main(void)
{
char c;
FILE *f1 = fopen("foo.txt", "rb");
FILE *f2 = fopen("bar.txt", "wb");
size_t ret;
while((ret = fread(&c, sizeof(c), 1, f1)))
ret = fwrite(&c, sizeof(c), 1, f2);
fclose(f1);
fclose(f2);
return 0;
}