Your sprintf call created the string
\x46ab
and you wrote those six characters to the file without further interpretation, so that's what you saw in the file (hex bytes 5c 78 34 36 61 62).
To get the hex-to-binary conversion you want, while avoiding byte order issues and anticipating the possibility of an arbitrary-length input string, you can do this one byte at a time with code like this:
char *p;
for(p = input; *p != '\0'; p += 2) {
unsigned int x;
if(sscanf(p, "%2x", &x) != 1) break;
putc(x, f);
}
This uses sscanf to convert the input string to hexadecimal, two characters (two hexadecimal digits, or one output byte) at a time.
I also tested it with a longer input string:
input = "0102034a4b4c";
This is quick-and-dirty, imperfect code. It will misbehave if input contains an odd number of characters, and it doesn't deal particularly gracefully with non-hexadecimal characters, either.
An improvement is to use the mildly obscure %n format specifier to scanf to discover exactly how many characters it consumed each time:
for(p = input; *p != '\0'; ) {
unsigned int x;
int n;
if(sscanf(p, "%2x%n", &x, &n) != 1) break;
putc(x, f);
p += n;
}
This should be more robust against malformed input strings, although I have not tested it exhaustively. (I hardly ever use functions in the scanf family, let alone the more obscure format specifiers like %n, but this is one of the few problems I know of where it's attractive, the alternatives being considerably more cumbersome.)
P.S. I got rid of your fseek call, because I wasn't sure what it was there for and it confused my testing. You can put it back in if you need it.
fwriteto write the data invaluedirectly to the file.snprintfandfputsare string/text operators. You cannot use that to produce binary data. All you need isfwrite(&value, sizeof(value), 1, f)