Convert Hexadecimal to String in C

When working with low-level data processing in C, developers often need to convert hexadecimal representations to human-readable strings. This operation is essential for tasks like network protocol analysis, binary file parsing, and embedded system debugging. Below I'll explain several practical approaches to achieve this conversion.

Method 1: Basic Character-by-Character Conversion

The simplest way involves processing each hexadecimal pair individually. Consider this implementation:

 void hex_to_str(const char* hex, char* output) {
    for(int i = 0; hex[i] && hex[i+1]; i += 2) {
        sscanf(hex + i, "%2hhx", &output[i/2]);
    }
} 

This method uses sscanf() with the "%2hhx" format specifier to process two-character chunks. While easy to implement, it lacks error checking and requires proper input formatting.

Line 1: Function declaration takes input hex string and output buffer. Note the use of const for input safety.

Loop condition: Continues until either hex[i] or hex[i+1] becomes null (end of string). Ensures we always process pairs.

sscanf breakdown:

Weakness: No validation for non-hex characters or odd-length inputs

Method 2: Manual Conversion with Validation

For better control and error handling, implement custom conversion logic:

int char_to_val(char c) {
    if(c >= '0' && c <= '9') return c - '0';
    if(c >= 'A' && c <= 'F') return 10 + (c - 'A');
    if(c >= 'a' && c <= 'f') return 10 + (c - 'a');
    return -1; // Invalid character
}

void safe_hex_convert(const char* hex, char* output) {
    int len = strlen(hex);
    if(len % 2 != 0) {
        printf("Invalid hex length");
        return;
    }
    
    for(int i = 0; i < len; i += 2) {
        int high = char_to_val(hex[i]);
        int low = char_to_val(hex[i+1]);
        
        if(high == -1 || low == -1) {
            printf("Invalid hex character");
            return;
        }
        
        output[i/2] = (high << 4) | low;
    }
}

1. char_to_val() Function

Purpose: Validates and converts individual hex characters to 4-bit values (nibbles)

2. safe_hex_convert() Workflow

  1. Initial Validation:
    • Checks input length parity using length % 2
    • Prevents processing incomplete bytes (e.g., "A3B")
  2. Byte Construction Loop:
    • Index Management: Steps by 2 using i += 2
    • Nibble Extraction:
      • high = First character's value
      • low = Second character's value
    • Error Propagation:
      • Checks return values from char_to_val()
      • Prints exact error location and invalid characters
  3. Bitwise Composition:
    • high << 4 shifts first nibble to high-order bits
    • | low combines with low-order bits
    • Example: high=0xC (1100), low=0xA (1010) → 0xCA (11001010)
  4. Output Finalization:
    • Adds null terminator at length/2 position
    • Ensures standard string termination

Important Considerations

1. Always validate input length (must be even number of characters)

2. Handle both uppercase and lowercase hex characters

3. Add null-terminator to output strings

4. Consider endianness for multi-byte values

For quick conversions without writing code, you can use our specialized hex to string converter tool that handles all edge cases automatically.

Practical Use Case Example

When processing network packets containing hex-encoded data:

 char packet[] = "48656C6C6F20576F726C64"; // "Hello World"
char decoded[256];
safe_hex_convert(packet, decoded);
printf("Decoded: %s", decoded); 

This fundamental skill becomes crucial when working with cryptographic hashes, memory dumps, or any binary data representation. The best implementation choice depends on specific requirements - use the sscanf() version for quick prototypes and the manual method for production-grade code requiring robust validation.