can the pre-processor convert string literals into chars?

S

steve.lorimer

I'm looking for a pre-processor command that will allow me to resolve
const
strings into const char literals at compile time.

Looking at the code below, I can take 5 characters and create a const
uint64_t value at compile time.
I can then create a switch statement that has these const values as
the
various cases.
Since each case resolves to an integer constant value at compile
time,
this switch statement is valid.

const uint64_t val1 = (static_cast<uint64_t>('S') << 32) | S
(static_cast<uint64_t>('T') << 24) | T
(static_cast<uint64_t>('A') << 16) | A
(static_cast<uint64_t>('R') << 8) | R
(static_cast<uint64_t>('T')); T

const char c1 = 'S', c2 = 'T', c3 = 'O', c4 = 'P';
const uint64_t val2 = (static_cast<uint64_t>(c1) << 32) | S
(static_cast<uint64_t>(c2) << 24) | T
(static_cast<uint64_t>(c3) << 16) | O
(static_cast<uint64_t>(c4) << 8) | P
(static_cast<uint64_t>(0));

uint64_t input = 0;
switch (input)
{
case val1: printf("input=val1\n"); break;
case val2: printf("input=val2\n"); break;
default: break;
}
//--------------------------------------------------------------------------

Now I attempt to repeat the above code, but instead of using literal
character
values, I use a const string literal.
gcc returns the following error:

error: case label does not reduce to an integer constant

So I guess the compiler is not able to resolve the index into the char
array at compile time.


const char* const str1 = "START";
const uint64_t val1 = (static_cast<uint64_t>(str1[0]) << 32) | S
(static_cast<uint64_t>(str1[1]) << 24) | T
(static_cast<uint64_t>(str1[2]) << 16) | A
(static_cast<uint64_t>(str1[3]) << 8) | R
(static_cast<uint64_t>(str1[4])); T

const char* const str2 = "STOP";
const uint64_t val2 = (static_cast<uint64_t>(str2[0]) << 32) | S
(static_cast<uint64_t>(str2[1]) << 24) | T
(static_cast<uint64_t>(str2[2]) << 16) | O
(static_cast<uint64_t>(str2[3]) << 8) | P
(static_cast<uint64_t>(str2[4]));

uint64_t input = 0;
switch (input)
{
case val1: printf("input=val1\n"); break;
case val2: printf("input=val2\n"); break;
default: break;
}
//--------------------------------------------------------------------------

What I actually have is a text file containing many unique input
strings,
each a maximum of 5 characters long.
Each of these input strings has a corresponding name and a value that
it maps to. I'd like to be able to create a switch statement with a
case for each of the
possible input strings which returns the associated value.
At run-time, I can create a uint64_t value from any 5 character input
string and run the value through my case statement to get a return
value. Obviously performance wise this is far better than:
if (strncmp(...))
return ...
else
if (strncmp(...))
return ...
else
ad infinitum


Please see my example data below:

<< input_values.txt >>
MACRO1(DO_START, "START", enum_val_start)
MACRO1(DO_STOP, "STOP", enum_val_stop)

// create const values
#undef MACRO1
#define MACRO1(NAME, INPUT, VALUE) \
const uint64_t val_##NAME = (static_cast<uint64_t>(INPUT[0])
<< 32) | \
(static_cast<uint64_t>(INPUT[1])
<< 24) | \
(static_cast<uint64_t>(INPUT[2])
<< 16) | \
(static_cast<uint64_t>(INPUT[3])
<< 8) | \
(static_cast<uint64_t>(INPUT[4]));
#include "input_values.txt"

// create switch statement containing above const values
#undef MACRO1
#define MACRO1(NAME, INPUT, VALUE) \
case val_##NAME: return VALUE;

switch (val)
{
#include "input_value.txt"
default: break;
}
//--------------------------------------------------------------------------
 
S

steve.lorimer


Are you saying that for a dataset of n 5-character strings, it could
be faster for the CPU to execute:

if (strncmp(input, str_1, 5) == 0) return val_1;
else
if (strncmp(input, str_2, 5) == 0) return val_2;
else
...
else
if (strncmp(input, str_n, 5) == 0) return val_n;

rather than this?

uint64_t val = convert_5_char_str_to_uint64(input);
switch(val)
{
case str_1_as_uint64: return val_1;
case str_2_as_uint64: return val_2;
...
case str_n_as_uint64: return val_n;
default: return -1;
}

Thanks, Steve
 
A

Alf P. Steinbach

* (e-mail address removed):
Are you saying that for a dataset of n 5-character strings, it could
be faster for the CPU to execute:

if (strncmp(input, str_1, 5) == 0) return val_1;
else
if (strncmp(input, str_2, 5) == 0) return val_2;
else
...
else
if (strncmp(input, str_n, 5) == 0) return val_n;

rather than this?

uint64_t val = convert_5_char_str_to_uint64(input);
switch(val)
{
case str_1_as_uint64: return val_1;
case str_2_as_uint64: return val_2;
...
case str_n_as_uint64: return val_n;
default: return -1;
}

I'm saying you're probably doing premature optimization.

The first is probably fast enough, no need to complicate.

Anyway, use a std::map, avoid non-standard types, etc.
 
S

steve.lorimer

I'm saying you're probably doing premature optimization.

The first is probably fast enough, no need to complicate.

Thanks Alf. Another question though. How can I measure 1st vs the 2nd,
if I can't get the 2nd to compile? :)

This is for a algorithmic trading system, where every micro-second
counts. Perhaps I am doing premature optimization, but I'm afraid my
knowledge of gcc and/or suncc optimizations is sparse, so I prefer to
err on the side of caution.
Anyway, use a std::map, avoid non-standard types, etc.

I did use this in the end... or at least something similar: a sorted
list with a binary search. Easy-peasy.
However, for interest's sake - I'm still keen to know if there is a
way to get the pre-processor to convert string literals into chars.

Any takers?! :)
TIA Steve
 
S

steve.lorimer

I'm saying you're probably doing premature optimization.

The first is probably fast enough, no need to complicate.
Please could someone who knows about the optimizations employed these
days answer this:

Can the optimizer convert

if (strncmp(input, str_1, 5) == 0) return val_1;
else
if (strncmp(input, str_2, 5) == 0) return val_2;
else
...
else
if (strncmp(input, str_n, 5) == 0) return val_n;

into a table-based lookup, such as what happens to switch statements?

My belief is that string compares are very expensive... but maybe
that's coz I'm too old-school!

If the compiler can optimize the above string-compare block into a
table -based lookup, then I say groovy! :)
 
A

Alf P. Steinbach

* (e-mail address removed):
Please could someone who knows about the optimizations employed these
days answer this:

Can the optimizer convert

if (strncmp(input, str_1, 5) == 0) return val_1;
else
if (strncmp(input, str_2, 5) == 0) return val_2;
else
...
else
if (strncmp(input, str_n, 5) == 0) return val_n;

into a table-based lookup, such as what happens to switch statements?

Generally not.

My belief is that string compares are very expensive... but maybe
that's coz I'm too old-school!

Sounds more like not-quite-out-of-school.

If the compiler can optimize the above string-compare block into a
table -based lookup, then I say groovy! :)

Yeah, that would be something.
 
S

steve.lorimer

Generally not.

Hence the reason I'm asking this question Alf! Like I said, every
micro-second counts.
Sounds more like not-quite-out-of-school.

What are you saying here... that string compares as opposed to a table-
based lookup are or are not faster? Please stay on topic and answer
the question. If I'm incorrect in saying string compares are
expensive, I'm happy to be told so, but please correct me rather than
attempting to insult me. A reasonable explanation would be fantastic.
Yeah, that would be something.

Again, the reson I ask the question... If you know the answers, please
reply. If not - please refrain from insults.
 
A

Alf P. Steinbach

* (e-mail address removed):
Hence the reason I'm asking this question Alf! Like I said, every
micro-second counts.


What are you saying here... that string compares as opposed to a table-
based lookup are or are not faster? Please stay on topic and answer
the question. If I'm incorrect in saying string compares are
expensive, I'm happy to be told so, but please correct me rather than
attempting to insult me. A reasonable explanation would be fantastic.


Again, the reson I ask the question... If you know the answers, please
reply. If not - please refrain from insults.

See above.
 
D

David Harmon

On 29 Mar 2007 07:36:01 -0700 in comp.lang.c++, (e-mail address removed)
wrote,
Can the optimizer convert ....
into a table-based lookup, such as what happens to switch statements?

The compiler will never generate a straight table indexed by a uint64_t.
That would be a table how many terrabytes in size? If you could even do
it, all your hoped for performance would disappear in cache thrashing.
The compiler will at best convert your very sparse switch statement into
a chain of if-else-if like tests.

The preceeding paragraph is guesswork. Never guess about performance.
If you need to know, measure.

As Alf said, use std::map, or consider some hashed unordered_map.
 
S

steve.lorimer

The compiler will never generate a straight table indexed by a uint64_t.
That would be a table how many terrabytes in size? If you could even do
it, all your hoped for performance would disappear in cache thrashing.
The compiler will at best convert your very sparse switch statement into
a chain of if-else-if like tests.

Thanks David - that's good help.
 

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

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,014
Latest member
BiancaFix3

Latest Threads

Top