In C, “hex to string” usually means one of two jobs:
- Hex text → bytes (parse
"48656c6c6f"into a buffer), then optionally treat those bytes as a C string. - Bytes → hex text for logging (the reverse).
C has no built-in hex codec — you parse pairs with strtoul/sscanf or a small table. Online check: Hex to String.
Parse hex into a buffer
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
/* returns byte count, or -1 on error */
int hex_to_bytes(const char *hex, unsigned char *out, size_t out_cap) {
size_t n = 0;
while (*hex) {
while (isspace((unsigned char)*hex)) hex++;
if (!*hex) break;
if (!isxdigit((unsigned char)hex[0]) || !isxdigit((unsigned char)hex[1]))
return -1;
if (n >= out_cap) return -1;
char pair[3] = { hex[0], hex[1], 0 };
out[n++] = (unsigned char)strtoul(pair, NULL, 16);
hex += 2;
}
return (int)n;
}
int main(void) {
unsigned char buf[64];
int n = hex_to_bytes("48 65 6c 6c 6f", buf, sizeof buf);
if (n < 0) return 1;
fwrite(buf, 1, (size_t)n, stdout); /* Hello */
putchar('\n');
return 0;
}
When the result is “a string”
/* Only valid if bytes are text without embedded NUL (or you track length). */
buf[n] = '\0';
puts((char *)buf);
Binary payloads must keep an explicit length. Do not assume NUL-terminated text.
Bytes to hex (debug)
void bytes_to_hex(const unsigned char *in, size_t n, char *out /* 2n+1 */) {
static const char *dig = "0123456789abcdef";
for (size_t i = 0; i < n; i++) {
out[i*2] = dig[in[i] >> 4];
out[i*2 + 1] = dig[in[i] & 0xF];
}
out[n*2] = '\0';
}
Pitfalls
- Odd number of hex digits → error; do not invent a leading zero unless a format requires it.
- Check buffer capacity before writing.
- UTF-8 multi-byte text is still just bytes in C — print with a UTF-8-aware console or keep length-aware APIs.
C++ developers may prefer higher-level helpers — see C++ hex to string. Concepts: hex encoding overview.