You can't fit 5 bytes worth of data into a 4 byte array; that leads to buffer overflows.
If you have the hex digits in a string, you can use sscanf() and a loop:
#include <stdio.h>
#include <ctype.h>
int main()
{
const char *src = "0011223344";
char buffer[5];
char *dst = buffer;
char *end = buffer + sizeof(buffer);
unsigned int u;
while (dst < end && sscanf(src, "%2x", &u) == 1)
{
*dst++ = u;
src += 2;
}
for (dst = buffer; dst < end; dst++)
printf("%d: %c (%d, 0x%02x)\n", dst - buffer,
(isprint(*dst) ? *dst : '.'), *dst, *dst);
return(0);
}
Note that printing the string starting with a zero-byte requires care; most operations terminate on the first null byte. Note that this code did not null-terminate the buffer; it is not clear whether null-termination is desirable, and there isn't enough space in the buffer I declared to add a terminal null (but that is readily fixed). There's a decent chance that if the code was packaged as a subroutine, it would need to return the length of the converted string (though you could also argue it is the length of the source string divided by two).
Answer from Jonathan Leffler on Stack OverflowYou can't fit 5 bytes worth of data into a 4 byte array; that leads to buffer overflows.
If you have the hex digits in a string, you can use sscanf() and a loop:
#include <stdio.h>
#include <ctype.h>
int main()
{
const char *src = "0011223344";
char buffer[5];
char *dst = buffer;
char *end = buffer + sizeof(buffer);
unsigned int u;
while (dst < end && sscanf(src, "%2x", &u) == 1)
{
*dst++ = u;
src += 2;
}
for (dst = buffer; dst < end; dst++)
printf("%d: %c (%d, 0x%02x)\n", dst - buffer,
(isprint(*dst) ? *dst : '.'), *dst, *dst);
return(0);
}
Note that printing the string starting with a zero-byte requires care; most operations terminate on the first null byte. Note that this code did not null-terminate the buffer; it is not clear whether null-termination is desirable, and there isn't enough space in the buffer I declared to add a terminal null (but that is readily fixed). There's a decent chance that if the code was packaged as a subroutine, it would need to return the length of the converted string (though you could also argue it is the length of the source string divided by two).
I would do something like this;
// Convert from ascii hex representation to binary
// Examples;
// "00" -> 0
// "2a" -> 42
// "ff" -> 255
// Case insensitive, 2 characters of input required, no error checking
int hex2bin( const char *s )
{
int ret=0;
int i;
for( i=0; i<2; i++ )
{
char c = *s++;
int n=0;
if( '0'<=c && c<='9' )
n = c-'0';
else if( 'a'<=c && c<='f' )
n = 10 + c-'a';
else if( 'A'<=c && c<='F' )
n = 10 + c-'A';
ret = n + ret*16;
}
return ret;
}
int main()
{
const char *in = "0011223344";
char out[5];
int i;
// Hex to binary conversion loop. For example;
// If in="0011223344" set out[] to {0x00,0x11,0x22,0x33,0x44}
for( i=0; i<5; i++ )
{
out[i] = hex2bin( in );
in += 2;
}
return 0;
}
This answers the original question, which asked for a C++ solution.
You can use an istringstream with the hex manipulator:
std::string hex_chars("E8 48 D8 FF FF 8B 0D");
std::istringstream hex_chars_stream(hex_chars);
std::vector<unsigned char> bytes;
unsigned int c;
while (hex_chars_stream >> std::hex >> c)
{
bytes.push_back(c);
}
Note that c must be an int (or long, or some other integer type), not a char; if it is a char (or unsigned char), the wrong >> overload will be called and individual characters will be extracted from the string, not hexadecimal integer strings.
Additional error checking to ensure that the extracted value fits within a char would be a good idea.
You'll never convince me that this operation is a performance bottleneck. The efficient way is to make good use of your time by using the standard C library:
static unsigned char gethex(const char *s, char **endptr) {
assert(s);
while (isspace(*s)) s++;
assert(*s);
return strtoul(s, endptr, 16);
}
unsigned char *convert(const char *s, int *length) {
unsigned char *answer = malloc((strlen(s) + 1) / 3);
unsigned char *p;
for (p = answer; *s; p++)
*p = gethex(s, (char **)&s);
*length = p - answer;
return answer;
}
Compiled and tested. Works on your example.
hash - Convert hex values to char array in C - Stack Overflow
Hex value in string to char array/data array
C hex character array to string representation - Stack Overflow
How to convert hex string to char array of hex in C/C++ - Stack Overflow
char * print_hex(const unsigned char *hash, const hashid type)
{
const char lookupTable[]="0123456789abcdef";
const size_t hashLength=mhash_get_block_size(type);
size_t i;
char * out=malloc(hashLength*2+1);
if(out==NULL)
return NULL;
for (i = 0; i < hashLength; i++)
{
out[i*2]=lookupTable[hash[i]>>4];
out[i*2+1]=lookupTable[hash[i]&0xf];
}
out[hashLength*2]=0;
return out;
}
Obviously the caller is responsible for freeing the returned string.
Still, as @K-Ballo correctly said in his answer, you don't need to convert to string form two hashes to compare them, all you need in that case is just a memcmp.
int compare_hashes(const unsigned char * hash1, const hashid hash1type, const unsigned char * hash2, const hashid hash2type)
{
if(hash1type!=hash2type)
return 0;
return memcmp(hash1, hash2, mhash_get_block_size(hash1type))==0;
}
How can I modify this function so that it returns a string?
You can print to a string variable using sprintf. I assume the hash size is fixed, so you know the size of your string would be number-of-chars-in-hash * 2 + 1. How to return that information is a typical problem in C, you can either return a malloced string that the user must then remember to free, or return a static string that will get replaced with the next call to the function (and makes the function non-reentrable). Personally I tend to avoid returning strings, instead having the function take a char* destination and a size.
(The goal being that I can compare the 2 values later)
Just compare the two hash variables in its raw form, you don't need strings for that.
int main()
{
char arr[4];
arr[0] = 0x11;
arr[1] = 0xc0;
arr[2] = 0x0c;
arr[3] = 0x00;
size_t len = sizeof(arr) / sizeof(*arr);
char* str = (char*)malloc(len * 2 + 1);
for (size_t i = 0; i < len; i++)
{
const static char table[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c','d','e','f' };
unsigned char c = (unsigned char)(arr[i]);
unsigned int lowbyte = c & 0x0f;
unsigned int highbyte = (c >> 4) & 0x0f;
str[2 * i] = table[highbyte];
str[2 * i + 1] = table[lowbyte];
}
str[2 * len] = '\0';
printf("%s\n",str);
return 0;
}
Convert each character to an unsigned character (so the 0xc0 isn't negative), then convert it to an integer and output as a two digit hexadecimal value.
#include <stdlib.h>
#include <stdio.h>
#define INT(x) ((int)(unsigned char)(x))
int main()
{
char arr[4];
arr[0] = 0x11;
arr[1] = 0xc0;
arr[2] = 0x0c;
arr[3] = 0x00;
char *str;
str=malloc(32);
sprintf(str, "%02x%02x%02x%02x",
INT(arr[0]), INT(arr[1]), INT(arr[2]), INT(arr[3]));
puts(str);
}
Output is:
11c00c00