128-bit hex number ---> string buffer

R

Richard Heathfield

ern said:
Does a function exist to convert a 128-bit hex number to a string?

There is no such thing as a "hex number". Hexadecimal is a numeric
representation system, not a kind of number.

If you have a hex representation, you already *have* a string, and
converting a string to a string is simple enough.
 
B

Ben Pfaff

ern said:
Does a function exist to convert a 128-bit hex number to a string?

What format is the number in to start out with? I ask because
it's strange to specify that a number is in hex if it's simply in
an integer variable. Normally, one thinks of a numeric variable
as simply having a value, and the base is not important. Also: C
doesn't guarantee the existence of an 128-bit integer type.
 
E

ern

Richard said:
ern said:


There is no such thing as a "hex number". Hexadecimal is a numeric
representation system, not a kind of number.

If you have a hex representation, you already *have* a string, and
converting a string to a string is simple enough.

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at above domain (but drop the www, obviously)

Let me rephrase. I have a 128 bit value, which I would like to be
converted to a hexadecimally represented string.

For example,

If my 128 bit value (represented hexadecimally) was:

4D9479E256DD4E8A923E32065141A911

I would want this function to populate a char buffer such that:

charBuffer = "4D9479E256DD4E8A923E32065141A911"
If you have a hex representation, you already *have* a string, and
converting a string to a string is simple enough.

Last time I checked... http://www.asciitable.com/

the string representation "4" has the hex value 0x34, contradicting
your above statement. You *always* have a string, though (as in this
case) it might not be the one you need.
 
W

Walter Roberson

ern said:
Does a function exist to convert a 128-bit hex number to a string?

There is no library function to do that directly, but you can
write it easily enough if you are willing to assume a specific
character set (such as ASCII), and if you know the encoding
represented by the number.

For example, one that would work for one encoding combination is,


#include <stdio.h>

int main(void) {
const char hexnum[33] = "54686520616e73776572206973203432";
unsigned short tmpbuf[16];
int i;

sscanf( hexnum,
"%2hx%2hx%2hx%2hx%2hx%2hx%2hx%2hx%2hx%2hx%2hx%2hx%2hx%2hx%2hx%2hx",
&tmpbuf[0], &tmpbuf[1], &tmpbuf[2], &tmpbuf[3],
&tmpbuf[4], &tmpbuf[5], &tmpbuf[6], &tmpbuf[7],
&tmpbuf[8], &tmpbuf[9], &tmpbuf[10], &tmpbuf[11],
&tmpbuf[12], &tmpbuf[13], &tmpbuf[14], &tmpbuf[15] );

for (i=0; i<16; i++) printf("%c", (unsigned char) tmpbuf );
printf("\n");

return 0;
}
 
R

Richard Heathfield

ern said:
Let me rephrase. I have a 128 bit value, which I would like to be
converted to a hexadecimally represented string.

Okay. Since C doesn't guarantee the existence of 128-bit integer types, let
us assume that you have your value in an array of unsigned char, which we
will treat as a bit array.

Here's some preprocessing stuff:

#include <stddef.h>
#include <limits.h>

#define BYTE(x) ((x) / CHAR_BIT)
#define BIT(x) ((x) % CHAR_BIT)
#define SET_BIT(a, b) \
(a)[BYTE(b)] |= (1 << (BIT(b)))
#define CLEAR_BIT(a, b) \
(a)[BYTE(b)] &= ~(1 << (BIT(b)))
#define TEST_BIT(a, b) \
(!!(((a)[BYTE(b)]) & (1 << (BIT(b)))))

Okay, here's our routine, which requires a pointer to the first of len bytes
of input and a pointer to the first of len * 2 + 1 bytes of output. I
should warn you that I have *not* tested it very much! Especially the code
that deals with weird byte sizes. So it's likely to have a hole or two. But
it should give you the general idea, and is not limited to 128-bit inputs
(but if that is what you want and CHAR_BIT is 8, then this routine expects
len to be 16):

void to_hex(char *out, unsigned char *in, size_t len)
{
char hexabet[] = "0123456789ABCDEF";
size_t bits = len * CHAR_BIT;
size_t bit = 0;
int ch = 0;

if(bits & 7)
{
bit = bits & 7; bits &= ~7;

while(bit != 0)
{
ch <<= 1;
ch |= TEST_BIT(in, bit);
--bit;
}
*out++ = hexabet[ch];
}

for(; bit < bits; bit += 8)
{
*out++ = hexabet[(TEST_BIT(in, bit + 7) << 3) |
(TEST_BIT(in, bit + 6) << 2) |
(TEST_BIT(in, bit + 5) << 1) |
TEST_BIT(in, bit + 4)];
*out++ = hexabet[(TEST_BIT(in, bit + 3) << 3) |
(TEST_BIT(in, bit + 2) << 2) |
(TEST_BIT(in, bit + 1) << 1) |
TEST_BIT(in, bit)];
}
*out = '\0';
}

And here's a driver:

#include <stdio.h>

int main(void)
{
unsigned char in[] =
{
0x4D, 0x94, 0x79, 0xE2,
0x56, 0xDD, 0x4E, 0x8A,
0x92, 0x3E, 0x32, 0x06,
0x51, 0x41, 0xA9, 0x11
};
char out[33] = {0};
to_hex(out, in, 16);
printf("%s\n", out);
return 0;
}


ASCII has nothing to do with C.
the string representation "4" has the hex value 0x34,

You seem to be confusing character sets, representations, and values. The
string "4" comprises two bytes, { '4', '\0' }. The code point of '4' is
implementation-defined. On some systems it is indeed 0x34, but on others
it's 0xF4 or some other value.
contradicting your above statement.

If it contradicts what I said, then it's wrong, because what I said is
right.
 
R

Richard Heathfield

Walter Roberson said:
There is no library function to do that directly, but you can
write it easily enough if you are willing to assume a specific
character set (such as ASCII),

You don't actually need to assume this. See my parallel reply.
 
E

ern

Walter said:
ern said:
Does a function exist to convert a 128-bit hex number to a string?

There is no library function to do that directly, but you can
write it easily enough if you are willing to assume a specific
character set (such as ASCII), and if you know the encoding
represented by the number.

For example, one that would work for one encoding combination is,


#include <stdio.h>

int main(void) {
const char hexnum[33] = "54686520616e73776572206973203432";
unsigned short tmpbuf[16];
int i;

sscanf( hexnum,
"%2hx%2hx%2hx%2hx%2hx%2hx%2hx%2hx%2hx%2hx%2hx%2hx%2hx%2hx%2hx%2hx",
&tmpbuf[0], &tmpbuf[1], &tmpbuf[2], &tmpbuf[3],
&tmpbuf[4], &tmpbuf[5], &tmpbuf[6], &tmpbuf[7],
&tmpbuf[8], &tmpbuf[9], &tmpbuf[10], &tmpbuf[11],
&tmpbuf[12], &tmpbuf[13], &tmpbuf[14], &tmpbuf[15] );

for (i=0; i<16; i++) printf("%c", (unsigned char) tmpbuf );
printf("\n");

return 0;
}


Thanks for the code, but that's the inverse of what I need.

Let me make the problem simpler. Say I have a 32-bit integer. I what
the hexadecimally represented string version.

So the integer is the INPUT, and the hexadecimally represented string
is the OUTPUT.
 
F

Frederick Gotham

ern posted:
If my 128 bit value (represented hexadecimally) was:

4D9479E256DD4E8A923E32065141A911

I would want this function to populate a char buffer such that:

charBuffer = "4D9479E256DD4E8A923E32065141A911"

If you have an aversion to the Standard Library, then maybe something along
the lines of the following. (This sample is capped at 32-Bit, but this is
easily adjusted.)

#include <assert.h>

#define MAX_VAL 0xFFFFFFFFu
#define MAX_DIVISOR 0x10000000u
#define MAX_HEX_DIGITS 8

typedef long unsigned IntType;

void IntToHexStr(IntType val,char *const buf)
{
int const assert_dummy = ( assert(val <= MAX_VAL),
assert(!!buf),
0);

static char const digits[16] = "0123456789ABCDEF";
/* No terminating null character */

IntType divisor = MAX_DIVISOR;

char *p = buf;

do
{
/* Maybe "ldiv" should be used... ? */

unsigned const digit_val = val / divisor;
val %= divisor;
divisor /= 0x10;

if(digit_val) *p++ = digits[digit_val];
} while(divisor);

if(buf==p) *p++ = '0';

*p = 0;
}

#include <stdlib.h>
#include <stdio.h>

int main(void)
{
char buf[MAX_HEX_DIGITS+1];

IntToHexStr(0x778FEE34,buf);

puts(buf);

return 0;
}
 
E

ern

Richard said:
ern said:
Let me rephrase. I have a 128 bit value, which I would like to be
converted to a hexadecimally represented string.

Okay. Since C doesn't guarantee the existence of 128-bit integer types, let
us assume that you have your value in an array of unsigned char, which we
will treat as a bit array.

Here's some preprocessing stuff:

#include <stddef.h>
#include <limits.h>

#define BYTE(x) ((x) / CHAR_BIT)
#define BIT(x) ((x) % CHAR_BIT)
#define SET_BIT(a, b) \
(a)[BYTE(b)] |= (1 << (BIT(b)))
#define CLEAR_BIT(a, b) \
(a)[BYTE(b)] &= ~(1 << (BIT(b)))
#define TEST_BIT(a, b) \
(!!(((a)[BYTE(b)]) & (1 << (BIT(b)))))

Okay, here's our routine, which requires a pointer to the first of len bytes
of input and a pointer to the first of len * 2 + 1 bytes of output. I
should warn you that I have *not* tested it very much! Especially the code
that deals with weird byte sizes. So it's likely to have a hole or two. But
it should give you the general idea, and is not limited to 128-bit inputs
(but if that is what you want and CHAR_BIT is 8, then this routine expects
len to be 16):

void to_hex(char *out, unsigned char *in, size_t len)
{
char hexabet[] = "0123456789ABCDEF";
size_t bits = len * CHAR_BIT;
size_t bit = 0;
int ch = 0;

if(bits & 7)
{
bit = bits & 7; bits &= ~7;

while(bit != 0)
{
ch <<= 1;
ch |= TEST_BIT(in, bit);
--bit;
}
*out++ = hexabet[ch];
}

for(; bit < bits; bit += 8)
{
*out++ = hexabet[(TEST_BIT(in, bit + 7) << 3) |
(TEST_BIT(in, bit + 6) << 2) |
(TEST_BIT(in, bit + 5) << 1) |
TEST_BIT(in, bit + 4)];
*out++ = hexabet[(TEST_BIT(in, bit + 3) << 3) |
(TEST_BIT(in, bit + 2) << 2) |
(TEST_BIT(in, bit + 1) << 1) |
TEST_BIT(in, bit)];
}
*out = '\0';
}

And here's a driver:

#include <stdio.h>

int main(void)
{
unsigned char in[] =
{
0x4D, 0x94, 0x79, 0xE2,
0x56, 0xDD, 0x4E, 0x8A,
0x92, 0x3E, 0x32, 0x06,
0x51, 0x41, 0xA9, 0x11
};
char out[33] = {0};
to_hex(out, in, 16);
printf("%s\n", out);
return 0;
}


ASCII has nothing to do with C.
the string representation "4" has the hex value 0x34,

You seem to be confusing character sets, representations, and values. The
string "4" comprises two bytes, { '4', '\0' }. The code point of '4' is
implementation-defined. On some systems it is indeed 0x34, but on others
it's 0xF4 or some other value.
contradicting your above statement.

If it contradicts what I said, then it's wrong, because what I said is
right.

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at above domain (but drop the www, obviously)

Thanks for the help all. I will try and apply the help to solve the
problem.
 
J

jmcgill

ern said:
Does a function exist to convert a 128-bit hex number to a string?


What's a 'hex number?' You mean like "Thirteen", or "666" ?



Or do you mean a "number" and its hexidecimal representation?

If so, then by "number", do you mean some sort of 128 bit Integer
format? There are int128_t and uint128_t on some platforms, which are
nonstandard. But there are also bignum libraries with 128 bit floating
point types.

If you are simply trying to take a 16 byte chunk of data, and convert
the value of each nybble to a hex digit in a string, isn't that just a
matter of using "%x" in some *printf() variety?
 
M

Michal Nazarewicz

ern said:
Let me make the problem simpler. Say I have a 32-bit integer. I what
the hexadecimally represented string version.

So the integer is the INPUT, and the hexadecimally represented string
is the OUTPUT.

#v+
sprintf(buffer, "%08x", integer);
#v-

Anyways, you probably ask for:

#v+
void binary2hex(const char *data, size_t len, char *buffer) {
static const char digits[16] = '0123456789ABCDEF";
size_t i = 0;
for (; i<len; ++i, ++data) {
*buffer++ = digits[(data>>4) & 0xf];
*buffer++ = digits[ data & 0xf];
}
*buffer = 0;
}
#v-

Not tested but should work. Buffer has to have at least 2*len+1 chars.
 
M

Michal Nazarewicz

Michal Nazarewicz said:
Anyways, you probably ask for:
void binary2hex(const char *data, size_t len, char *buffer) {

Duh... Even though it doesn't make big difference it shall be:

#v+
void binary2hex(const unsigned char *data, size_t len, char *buffer) {
#v-

The code will of course fail if CHAR_BIT != 8.
 
J

jmcgill

ern said:
Thanks for the code, but that's the inverse of what I need.

Let me make the problem simpler. Say I have a 32-bit integer. I what
the hexadecimally represented string version.

So the integer is the INPUT, and the hexadecimally represented string
is the OUTPUT.

To do numeric types greater than 32-bits will require a nonstandard type.

#include <stdio.h>
int main(int argc, char** argv){
long unsigned int num;
num = 0xCAFEBABEUL;
printf("0x%8lX\n", num);
return 0;
}
 
E

Elijah Cardon

Ben Pfaff said:
What format is the number in to start out with? I ask because
it's strange to specify that a number is in hex if it's simply in
an integer variable. Normally, one thinks of a numeric variable
as simply having a value, and the base is not important. Also: C
doesn't guarantee the existence of an 128-bit integer type.
We miss you, Dan. Elijah
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,764
Messages
2,569,567
Members
45,041
Latest member
RomeoFarnh

Latest Threads

Top