Developer Guide

Convert Hexadecimal to String in C (Parse Bytes Safely)

In C, “hex to string” usually means one of two jobs:

  1. Hex text → bytes (parse "48656c6c6f" into a buffer), then optionally treat those bytes as a C string.
  2. 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

C++ developers may prefer higher-level helpers — see C++ hex to string. Concepts: hex encoding overview.