can the pre-processor convert string literals into chars?

Discussion in 'C++' started by steve.lorimer@gmail.com, Mar 29, 2007.

  1. Guest

    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;
    }
    //--------------------------------------------------------------------------
     
    , Mar 29, 2007
    #1
    1. Advertising

  2. * :
    > Obviously performance wise this is far better than:


    Measure.

    --
    A: Because it messes up the order in which people normally read text.
    Q: Why is it such a bad thing?
    A: Top-posting.
    Q: What is the most annoying thing on usenet and in e-mail?
     
    Alf P. Steinbach, Mar 29, 2007
    #2
    1. Advertising

  3. Guest

    On Mar 29, 3:08 pm, "Alf P. Steinbach" <> wrote:
    >
    > Measure.
    >


    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
     
    , Mar 29, 2007
    #3
  4. * :
    > On Mar 29, 3:08 pm, "Alf P. Steinbach" <> wrote:
    >> Measure.
    >>

    >
    > 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.

    --
    A: Because it messes up the order in which people normally read text.
    Q: Why is it such a bad thing?
    A: Top-posting.
    Q: What is the most annoying thing on usenet and in e-mail?
     
    Alf P. Steinbach, Mar 29, 2007
    #4
  5. Guest

    On Mar 29, 3:20 pm, "Alf P. Steinbach" <> wrote:
    > 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
     
    , Mar 29, 2007
    #5
  6. Guest

    On Mar 29, 3:20 pm, "Alf P. Steinbach" <> wrote:
    >
    > 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! :)
     
    , Mar 29, 2007
    #6
  7. * :
    > On Mar 29, 3:20 pm, "Alf P. Steinbach" <> wrote:
    >> 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?


    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.

    --
    A: Because it messes up the order in which people normally read text.
    Q: Why is it such a bad thing?
    A: Top-posting.
    Q: What is the most annoying thing on usenet and in e-mail?
     
    Alf P. Steinbach, Mar 29, 2007
    #7
  8. Guest

    On Mar 29, 3:40 pm, "Alf P. Steinbach" <> wrote:
    > 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.
     
    , Mar 29, 2007
    #8
  9. * :
    > On Mar 29, 3:40 pm, "Alf P. Steinbach" <> wrote:
    >> 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.


    See above.

    --
    A: Because it messes up the order in which people normally read text.
    Q: Why is it such a bad thing?
    A: Top-posting.
    Q: What is the most annoying thing on usenet and in e-mail?
     
    Alf P. Steinbach, Mar 29, 2007
    #9
  10. David Harmon Guest

    On 29 Mar 2007 07:36:01 -0700 in comp.lang.c++,
    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.
     
    David Harmon, Mar 29, 2007
    #10
  11. Guest

    On Mar 29, 7:03 pm, David Harmon <> wrote:
    >
    > 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.
     
    , Apr 2, 2007
    #11
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. John Goche
    Replies:
    8
    Views:
    16,574
  2. pre-processor string replacement

    , Jan 14, 2007, in forum: C Programming
    Replies:
    11
    Views:
    447
    Thad Smith
    Jan 14, 2007
  3. Replies:
    0
    Views:
    331
  4. Replies:
    2
    Views:
    538
    James Kanze
    Mar 30, 2007
  5. Hongyu
    Replies:
    9
    Views:
    967
    James Kanze
    Aug 8, 2008
Loading...

Share This Page