declaring long hex strings?

A

arekkusu

Hello, I have the following problem:

when declaring hex data in C, you typically do something like:
const char[] = {0xde, 0xad, 0xbe, 0xef, 0x01, 0x02, 0x03, 0x04 ... };

This is quite verbose and makes the source hard to read.

An alternative is something like
const char[] = "deadbeef01020304";

but this doubles the storage requirements since each nybble is
converted to an ASCII char.

Some old assemblers have HEX directives for declaring large chunks of
raw data. My question is: is there any way to do this in C? Excessive
preprocessor acrobatics are OK as long as they work in gcc...

The hex data I have is several thousand strings like:
CRC(b746de6d) SHA1(ea69f87f84ded1f0a66457af24cbc692e5ff67e3)

Really, I just want a preprocessor macro that does a trivial regex like
s/([a-fA-F0-9][a-fA-F0-9])/0x\1,/ is that possible?
 
M

Michael Mair

Hello, I have the following problem:

when declaring hex data in C, you typically do something like:
const char[] = {0xde, 0xad, 0xbe, 0xef, 0x01, 0x02, 0x03, 0x04 ... };

Better
const unsigned char[] = ....
0x** is an unsigned int value and the conversion to char can cause
an overflow if char is signed which leads to undefined behaviour.
This is quite verbose and makes the source hard to read.
Indeed.


An alternative is something like
const char[] = "deadbeef01020304";

but this doubles the storage requirements since each nybble is
converted to an ASCII char.

Nope. C does not specify anything about character encoding;
we can as well use EBCDIC or anything else. The 4bit nibbles
are represented by a character which has CHAR_BIT bits.

Some old assemblers have HEX directives for declaring large chunks of
raw data. My question is: is there any way to do this in C? Excessive
preprocessor acrobatics are OK as long as they work in gcc...

The hex data I have is several thousand strings like:
CRC(b746de6d) SHA1(ea69f87f84ded1f0a66457af24cbc692e5ff67e3)

Really, I just want a preprocessor macro that does a trivial regex like
s/([a-fA-F0-9][a-fA-F0-9])/0x\1,/ is that possible?

I fear you won't get that; the preprocessor cannot split preprocessing
tokens.

Some possibilities:
If you have file I/O on your target system: Store your data chunks
in text or binary files and retrieve them at runtime. May even make
the whole thing more flexible.
Have a look at a general purpose preprocessor or a script language
with regexps and produce data files which will get converted to
the required C data which in turn can be #included where appropriate.
Third: If you are daring, you can fake a preprocesser macro; you "call"
e.g. const unsigned char[] = HEXARRAY(deadbeef....);
and apply, say, a perl script to your source before you go through
preprocessing and compilation; this is a viable solution if you use
makefiles.


Cheers
Michael
 
A

Andrey Tarasevich

...
when declaring hex data in C, you typically do something like:
const char[] = {0xde, 0xad, 0xbe, 0xef, 0x01, 0x02, 0x03, 0x04 ... };

This is quite verbose and makes the source hard to read.

An alternative is something like
const char[] = "deadbeef01020304";

but this doubles the storage requirements since each nybble is
converted to an ASCII char.

You can also use

const char[] = "\xde\xad\xbe\xef\x01\x02\x03\x04";

although this is not much less verbose than the original version.
 
P

pete

Michael said:
0x** is an unsigned int value and the conversion to char can cause
an overflow if char is signed which leads to undefined behaviour.

0x01 is an expression of type int, not unsigned.

Conversion of an out of range value, to a signed integer type,
is implementation defined, not undefined.
 
M

Michael Mair

pete said:
0x01 is an expression of type int, not unsigned.

Conversion of an out of range value, to a signed integer type,
is implementation defined, not undefined.

Argh. Note to self: Do not put the standard into some unmarked
box when moving...
Right, I don't know what I was thinking (too late for thinking,
probably). Thank you :)


Cheers
Michael
 
A

arekkusu

Thanks for the replies.

It looks like there is no way to trick the preprocessor to do this. :(
Sadly in my case external files and additional preprocess passes are
not possible.

That leaves: ugly code. :(
 
P

Peter Nilsson

Hello, I have the following problem:

when declaring hex data in C, you typically do something like:
const char[] = {0xde, 0xad, 0xbe, 0xef, 0x01, 0x02, 0x03, 0x04 ... };

This is quite verbose and makes the source hard to read.

An alternative is something like
const char[] = "deadbeef01020304";

but this doubles the storage requirements since each nybble is
converted to an ASCII char.

Some old assemblers have HEX directives for declaring large chunks of
raw data. My question is: is there any way to do this in C? Excessive
preprocessor acrobatics are OK as long as they work in gcc...

The hex data I have is several thousand strings like:
CRC(b746de6d) SHA1(ea69f87f84ded1f0a66457af24cbc692e5ff67e3)

Really, I just want a preprocessor macro that does a trivial regex like
s/([a-fA-F0-9][a-fA-F0-9])/0x\1,/ is that possible?

If you're willing to split it up, you can do something like...

#define SHA1(p,q,r,s,t) \
SPLIT(p), SPLIT(q), SPLIT(r), SPLIT(s), SPLIT(t)

#define CAT(x,y) x ##y
#define CAT2(x,y) CAT(x,y)

#define SPLIT(x) SPLIT4(CAT2(0x0,x))
#define SPLIT4(x) \
(x >> 24) & 0xFF, \
(x >> 16) & 0xFF, \
(x >> 8) & 0xFF, \
(x ) & 0xFF

unsigned char x[] =
{ SHA1(ea69f87f, 84ded1f0, a66457af, 24cbc692, e5ff67e3),
SHA1(deadbeef, aaaaaaaa, 55555555, 12345678, 90abcdef) };

#include <stdio.h>

int main(void)
{
size_t i;
for (i = 0; i < sizeof x; i++)
printf(" %02X", 0u + x);
puts("");
return 0;
}
 
P

pete

Michael said:
Argh. Note to self: Do not put the standard into some unmarked
box when moving...
Right, I don't know what I was thinking (too late for thinking,
probably). Thank you :)

You're welcome. I just thought of a C riddle.
#define A, B, and C, such that this expression
(A > B && B > C && A == C)
becomes a constant expression with a value of 1.
 
B

Ben Pfaff

pete said:
I just thought of a C riddle.
#define A, B, and C, such that this expression
(A > B && B > C && A == C)
becomes a constant expression with a value of 1.

#define A 1 || (0
#define B 0
#define C 0)

The 1 may be replaced by an arbitrary nonzero value of your choice.
Each 0 may be replaced by an arbitrary value of your choice.
 
M

Michael Mair

pete said:
You're welcome. I just thought of a C riddle.
#define A, B, and C, such that this expression
(A > B && B > C && A == C)
becomes a constant expression with a value of 1.

*g*

#include <stdio.h>

#define STRINGIZE(s) #s
#define STRINGIZE2(s,t) "\""#s ", "#t"\""
#define XSTR(s) STRINGIZE(s)
#define XSTR2(s) STRINGIZE2(s)
#define EVAL \
printf("Evaluates (%s,%s,%s) to %d\n",\
XSTR(A),XSTR(B),XSTR(C),(A > B && B > C && A == C))
#define EVAL2 \
printf("Evaluates (%s,%s,%s) to %d\n",\
XSTR(A),XSTR(B),XSTR2(C),(A > B && B > C && A == C))

int main (void)
{
#define A 1||-1000
#define B -500
#define C 0
EVAL;
#undef A
#undef B
#undef C
#define A -1000
#define B -500
#define C 0, 1
EVAL2;
#undef A
#undef B
#undef C
#define A -1000
#define B -500
#define C 0 ? 0 : 1
EVAL;
#undef A
#undef B
#undef C
#define A (unsigned) C
#define B 0
#define C -1
EVAL;
#undef A
#undef B
#undef C

return 0;
}
 
P

pete

Ben said:
#define A 1 || (0
#define B 0
#define C 0)

The 1 may be replaced by an arbitrary nonzero value of your choice.
Each 0 may be replaced by an arbitrary value of your choice.

I should have used more parentheses.
((A) > (B) && (B) > (C) && (A) == (C))

This is what I had in mind:
#define A (0)
#define B (-1)
#define C (0u)
 
P

pete

#define A 1||-1000
#define B -500
#define C 0
EVAL;
#undef A
#undef B
#undef C
#define A -1000
#define B -500
#define C 0, 1
EVAL2;
#undef A
#undef B
#undef C
#define A -1000
#define B -500
#define C 0 ? 0 : 1
EVAL;
#undef A
#undef B
#undef C
#define A (unsigned) C
#define B 0
#define C -1

That last set was closest to what I was thinking.
Thanks.
 

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,780
Messages
2,569,611
Members
45,280
Latest member
BGBBrock56

Latest Threads

Top