[c] Convert hex string (char []) to int?

I have a char[] that contains a value such as "0x1800785" but the function I want to give the value to requires an int, how can I convert this to an int? I have searched around but cannot find an answer. Thanks.

This question is related to c char int

The answer is


So, after a while of searching, and finding out that strtol is quite slow, I've coded my own function. It only works for uppercase on letters, but adding lowercase functionality ain't a problem.

int hexToInt(PCHAR _hex, int offset = 0, int size = 6)
{
    int _result = 0;
    DWORD _resultPtr = reinterpret_cast<DWORD>(&_result);
    for(int i=0;i<size;i+=2)
    {
        int _multiplierFirstValue = 0, _addonSecondValue = 0;

        char _firstChar = _hex[offset + i];
        if(_firstChar >= 0x30 && _firstChar <= 0x39)
            _multiplierFirstValue = _firstChar - 0x30;
        else if(_firstChar >= 0x41 && _firstChar <= 0x46)
            _multiplierFirstValue = 10 + (_firstChar - 0x41);

        char _secndChar = _hex[offset + i + 1];
        if(_secndChar >= 0x30 && _secndChar <= 0x39)
            _addonSecondValue = _secndChar - 0x30;
        else if(_secndChar >= 0x41 && _secndChar <= 0x46)
            _addonSecondValue = 10 + (_secndChar - 0x41);

        *(BYTE *)(_resultPtr + (size / 2) - (i / 2) - 1) = (BYTE)(_multiplierFirstValue * 16 + _addonSecondValue);
    }
    return _result;
}

Usage:

char *someHex = "#CCFF00FF";
int hexDevalue = hexToInt(someHex, 1, 8);

1 because the hex we want to convert starts at offset 1, and 8 because it's the hex length.

Speedtest (1.000.000 calls):

strtol ~ 0.4400s
hexToInt ~ 0.1100s

Have you tried strtol()?

strtol - convert string to a long integer

Example:

const char *hexstring = "abcdef0";
int number = (int)strtol(hexstring, NULL, 16);

In case the string representation of the number begins with a 0x prefix, one must should use 0 as base:

const char *hexstring = "0xabcdef0";
int number = (int)strtol(hexstring, NULL, 0);

(It's as well possible to specify an explicit base such as 16, but I wouldn't recommend introducing redundancy.)


One quick & dirty solution:

// makes a number from two ascii hexa characters
int ahex2int(char a, char b){

    a = (a <= '9') ? a - '0' : (a & 0x7) + 9;
    b = (b <= '9') ? b - '0' : (b & 0x7) + 9;

    return (a << 4) + b;
}

You have to be sure your input is correct, no validation included (one could say it is C). Good thing it is quite compact, it works with both 'A' to 'F' and 'a' to 'f'.

The approach relies on the position of alphabet characters in the ASCII table, let's peek e.g. to Wikipedia (https://en.wikipedia.org/wiki/ASCII#/media/File:USASCII_code_chart.png). Long story short, the numbers are below the characters, so the numeric characters (0 to 9) are easily converted by subtracting the code for zero. The alphabetic characters (A to F) are read by zeroing other than last three bits (effectively making it work with either upper- or lowercase), subtracting one (because after the bit masking, the alphabet starts on position one) and adding ten (because A to F represent 10th to 15th value in hexadecimal code). Finally, we need to combine the two digits that form the lower and upper nibble of the encoded number.

Here we go with same approach (with minor variations):

#include <stdio.h>

// takes a null-terminated string of hexa characters and tries to 
// convert it to numbers
long ahex2num(unsigned char *in){

    unsigned char *pin = in; // lets use pointer to loop through the string
    long out = 0;  // here we accumulate the result

    while(*pin != 0){
        out <<= 4; // we have one more input character, so 
                   // we shift the accumulated interim-result one order up
        out +=  (*pin < 'A') ? *pin & 0xF : (*pin & 0x7) + 9; // add the new nibble
        pin++; // go ahead
    }

    return out;
}

// main function will test our conversion fn
int main(void) {

    unsigned char str[] = "1800785";  // no 0x prefix, please
    long num;

    num = ahex2num(str);  // call the function

    printf("Input: %s\n",str);  // print input string
    printf("Output: %x\n",num);  // print the converted number back as hexa
    printf("Check: %ld = %ld \n",num,0x1800785);  // check the numeric values matches

    return 0;
}

I made a librairy to make Hexadecimal / Decimal conversion without the use of stdio.h. Very simple to use :

unsigned hexdec (const char *hex, const int s_hex);

Before the first conversion intialize the array used for conversion with :

void init_hexdec ();

Here the link on github : https://github.com/kevmuret/libhex/


This is a function to directly convert hexadecimal containing char array to an integer which needs no extra library:

int hexadecimal2int(char *hdec) {
    int finalval = 0;
    while (*hdec) {
        
        int onebyte = *hdec++; 
        
        if (onebyte >= '0' && onebyte <= '9'){onebyte = onebyte - '0';}
        else if (onebyte >= 'a' && onebyte <='f') {onebyte = onebyte - 'a' + 10;}
        else if (onebyte >= 'A' && onebyte <='F') {onebyte = onebyte - 'A' + 10;}  
        
        finalval = (finalval << 4) | (onebyte & 0xF);
    }
    finalval = finalval - 524288;
    return finalval;
}

Assuming you mean it's a string, how about strtol?


Something like this could be useful:

char str[] = "0x1800785";
int num;

sscanf(str, "%x", &num);
printf("0x%x %i\n", num, num); 

Read man sscanf


Use strtol if you have libc available like the top answer suggests. However if you like custom stuff or are on a microcontroller without libc or so, you may want a slightly optimized version without complex branching.

#include <inttypes.h>


/**
 * xtou64
 * Take a hex string and convert it to a 64bit number (max 16 hex digits).
 * The string must only contain digits and valid hex characters.
 */
uint64_t xtou64(const char *str)
{
    uint64_t res = 0;
    char c;

    while ((c = *str++)) {
        char v = (c & 0xF) + (c >> 6) | ((c >> 3) & 0x8);
        res = (res << 4) | (uint64_t) v;
    }

    return res;
} 

The bit shifting magic boils down to: Just use the last 4 bits, but if it is an non digit, then also add 9.


Try below block of code, its working for me.

char *p = "0x820";
uint16_t intVal;
sscanf(p, "%x", &intVal);

printf("value x: %x - %d", intVal, intVal);

Output is:

value x: 820 - 2080

Or if you want to have your own implementation, I wrote this quick function as an example:

/**
 * hex2int
 * take a hex string and convert it to a 32bit number (max 8 hex digits)
 */
uint32_t hex2int(char *hex) {
    uint32_t val = 0;
    while (*hex) {
        // get current character then increment
        uint8_t byte = *hex++; 
        // transform hex character to the 4bit equivalent number, using the ascii table indexes
        if (byte >= '0' && byte <= '9') byte = byte - '0';
        else if (byte >= 'a' && byte <='f') byte = byte - 'a' + 10;
        else if (byte >= 'A' && byte <='F') byte = byte - 'A' + 10;    
        // shift 4 to make space for new digit, and add the 4 bits of the new digit 
        val = (val << 4) | (byte & 0xF);
    }
    return val;
}

I know this is really old but I think the solutions looked too complicated. Try this in VB:

Public Function HexToInt(sHEX as String) as long
Dim iLen as Integer
Dim i as Integer 
Dim SumValue as Long 
Dim iVal as long
Dim AscVal as long

    iLen = Len(sHEX)
    For i = 1 to Len(sHEX)
      AscVal = Asc(UCase(Mid$(sHEX, i,  1)))
      If AscVal >= 48 And AscVal  <= 57 Then
        iVal  = AscVal - 48
      ElseIf AscVal >= 65 And AscVal <= 70 Then
        iVal = AscVal - 55
      End If 
      SumValue = SumValue + iVal * 16 ^ (iLen- i)
    Next i 
    HexToInt  = SumValue
End Function 

i have done a similar thing, think it might help u its actually working for me

int main(){ int co[8],i;char ch[8];printf("please enter the string:");scanf("%s",ch);for(i=0;i<=7;i++){if((ch[i]>='A')&&(ch[i]<='F')){co[i]=(unsigned int)ch[i]-'A'+10;}else if((ch[i]>='0')&&(ch[i]<='9')){co[i]=(unsigned int)ch[i]-'0'+0;}}

here i have only taken a string of 8 characters. if u want u can add similar logic for 'a' to 'f' to give their equivalent hex values,i haven't done that cause i didn't needed it.


Examples related to c

conflicting types for 'outchar' Can't compile C program on a Mac after upgrade to Mojave Program to find largest and second largest number in array Prime numbers between 1 to 100 in C Programming Language In c, in bool, true == 1 and false == 0? How I can print to stderr in C? Visual Studio Code includePath "error: assignment to expression with array type error" when I assign a struct field (C) Compiling an application for use in highly radioactive environments How can you print multiple variables inside a string using printf?

Examples related to char

How can I convert a char to int in Java? C# - How to convert string to char? How to take character input in java Char Comparison in C Convert Char to String in C cannot convert 'std::basic_string<char>' to 'const char*' for argument '1' to 'int system(const char*)' How to get the real and total length of char * (char array)? Why is conversion from string constant to 'char*' valid in C but invalid in C++ char *array and char array[] C++ - How to append a char to char*?

Examples related to int

How can I convert a char to int in Java? How to take the nth digit of a number in python "OverflowError: Python int too large to convert to C long" on windows but not mac Pandas: Subtracting two date columns and the result being an integer Convert bytes to int? How to round a Double to the nearest Int in swift? Leading zeros for Int in Swift C convert floating point to int Convert Int to String in Swift Converting String to Int with Swift