"multiple putchar()'s" versus "collect chars in char-array and use puts()" - speed/efficiency

Discussion in 'C Programming' started by anon.asdf@gmail.com, Oct 11, 2007.

  1. Guest

    In terms of efficieny:

    Is it better to use multiple putchar()'s after one another as one gets
    to new char's

    OR

    is it better to collect the characters to a char-array first, and then
    use puts() to print to screen
    ????



    /******* ExampleA **********/
    /**** collect chars and then call puts ****/

    char symbols[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
    'A', 'B', 'C', 'D', 'E', 'F'};

    #define uchar2hex(char_ptr, str_ptr) \
    *str_ptr++ = symbols[((unsigned char)*char_ptr) >> 4]; \
    *str_ptr++ = symbols[((unsigned char)*char_ptr++) & 0xF]; \
    *str_ptr++ = ' ';

    {
    int i;
    char source[29] = "asdfasdfasdfasdfsadfasdfasdf";
    char *src_ptr = source;
    char dest[29];
    char *dest_ptr = dest;

    for (i = 0; i < 29; i++) {
    uchar2hex(src_ptr, dest_ptr);
    }
    *dest_ptr = '\0';
    puts(dest);
    }

    /********* ExampleB *************/
    /***** putchar() as each new char is encountered ******/

    char symbols[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
    'A', 'B', 'C', 'D', 'E', 'F'};

    #define uchar2hex2(char_ptr, str_ptr) \
    putchar(*str_ptr++ = symbols[((unsigned char)*char_ptr) >> 4]); \
    putchar(*str_ptr++ = symbols[((unsigned char)*char_ptr++) & 0xF]); \
    putchar(*str_ptr++ = ' ');

    {
    int i;
    char source[29] = "asdfasdfasdfasdfsadfasdfasdf";
    char *src_ptr = source;
    char dest[29];
    char *dest_ptr = dest;

    for (i = 0; i < 29; i++) {
    uchar2hex2(src_ptr, dest_ptr);
    }
    *dest_ptr = '\0';
    }
    , Oct 11, 2007
    #1
    1. Advertising

  2. Guest

    On Oct 11, 2:54 am, <<<Albert - forgot to sign the
    root post>>> wrote:
    <snip>

    > char symbols[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
    > 'A', 'B', 'C', 'D', 'E', 'F'};
    >
    > #define uchar2hex(char_ptr, str_ptr) \
    > *str_ptr++ = symbols[((unsigned char)*char_ptr) >> 4]; \
    > *str_ptr++ = symbols[((unsigned char)*char_ptr++) & 0xF]; \


    <snip>

    Is there a faster way of converting a 8-bit char to its 2-digit hex
    representation?

    Regards,
    Albert
    , Oct 11, 2007
    #2
    1. Advertising

  3. Eric Sosman Guest

    Re: "multiple putchar()'s" versus "collect chars in char-array anduse puts()" - speed/efficiency

    wrote:
    > In terms of efficieny:
    >
    > Is it better to use multiple putchar()'s after one another as one gets
    > to new char's
    >
    > OR
    >
    > is it better to collect the characters to a char-array first, and then
    > use puts() to print to screen


    The C Standard says next to nothing about efficiency, even
    though "efficiency" is one of the principal reasons people turn
    to C nowadays. However, in regard to the question you ask the
    Standard, unusually, offers an unequivocal answer: "Yes!" (See
    Section 6.5.14; see also http://www.c-faq.com/ Question 20.13.)

    --
    Eric Sosman
    lid
    Eric Sosman, Oct 11, 2007
    #3
  4. Gene Guest

    On Oct 10, 9:10 pm, wrote:
    > On Oct 11, 2:54 am, <<<Albert - forgot to sign theroot post>>> wrote:
    >
    > <snip>
    >
    > > char symbols[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
    > > 'A', 'B', 'C', 'D', 'E', 'F'};

    >
    > > #define uchar2hex(char_ptr, str_ptr) \
    > > *str_ptr++ = symbols[((unsigned char)*char_ptr) >> 4]; \
    > > *str_ptr++ = symbols[((unsigned char)*char_ptr++) & 0xF]; \

    >
    > <snip>
    >
    > Is there a faster way of converting a 8-bit char to its 2-digit hex
    > representation?


    Well, you can do it without the global table. Though this probably
    won't be faster, it ought not to be slower.

    #define uchar2hex(P, S) do { \
    *(P)++ = "0123456789ABCDEF"[(int)(unsigned char)*(S)]; \
    *(P)++ = "0123456789ABCDEF"[(int)(unsigned char)*(S)++ & 0xF]; }
    while (0)

    Using a 256x2 table would probably be slightly faster.

    char hex[][2] = { { '0', '0' }, ... };

    #define uchar2hex(P, S) do { \
    memcpy(P, hex[(int)(unsigned char)*(S)++], 2);
    (P) += 2; } while (0)

    especially if your compiler open codes the memcpy.
    Gene, Oct 11, 2007
    #4
  5. Gene <> writes:
    > On Oct 10, 9:10 pm, wrote:
    >> On Oct 11, 2:54 am, <<<Albert - forgot to sign theroot post>>> wrote:
    >>
    >> <snip>
    >>
    >> > char symbols[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
    >> > 'A', 'B', 'C', 'D', 'E', 'F'};

    >>
    >> > #define uchar2hex(char_ptr, str_ptr) \
    >> > *str_ptr++ = symbols[((unsigned char)*char_ptr) >> 4]; \
    >> > *str_ptr++ = symbols[((unsigned char)*char_ptr++) & 0xF]; \

    >>
    >> <snip>
    >>
    >> Is there a faster way of converting a 8-bit char to its 2-digit hex
    >> representation?

    >
    > Well, you can do it without the global table. Though this probably
    > won't be faster, it ought not to be slower.
    >
    > #define uchar2hex(P, S) do { \
    > *(P)++ = "0123456789ABCDEF"[(int)(unsigned char)*(S)]; \
    > *(P)++ = "0123456789ABCDEF"[(int)(unsigned char)*(S)++ & 0xF]; }
    > while (0)
    >
    > Using a 256x2 table would probably be slightly faster.
    >
    > char hex[][2] = { { '0', '0' }, ... };
    >
    > #define uchar2hex(P, S) do { \
    > memcpy(P, hex[(int)(unsigned char)*(S)++], 2);
    > (P) += 2; } while (0)
    >
    > especially if your compiler open codes the memcpy.


    The "do { ... } while (0)" trick is an improvement over the original
    macro definition, since it allows it to be used in any statement
    context. But since the macro definition consists entirely of
    expressions, it's better to just define it as a single expression.

    Re-writing the original macro (without changing what it does) yields:

    #define uchar2hex(char_ptr, str_ptr) \
    ( *(str_ptr)++ = symbols[((unsigned char)*(char_ptr)) >> 4], \
    *(str_ptr)++ = symbols[((unsigned char)*(char_ptr)++) & 0xF], \
    *(str_ptr)++ = ' ' )

    (The last line was lost in a quoting mishap.)

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
    Keith Thompson, Oct 11, 2007
    #5
  6. Guest

    On Oct 11, 3:33 am, Eric Sosman <> wrote:
    > wrote:
    > > In terms of efficieny:

    >
    > > Is it better to use multiple putchar()'s after one another as one gets
    > > to new char's

    >
    > > OR

    >
    > > is it better to collect the characters to a char-array first, and then
    > > use puts() to print to screen

    >
    > The C Standard says next to nothing about efficiency, even
    > though "efficiency" is one of the principal reasons people turn
    > to C nowadays. However, in regard to the question you ask the
    > Standard, unusually, offers an unequivocal answer: "Yes!"


    "Yes" to the first part (use multiple putchar()'s) OR "yes" to the
    second part (collect and use puts()) ???

    I suspect you mean "yes" to the 2nd part, since there puts() works at
    a low level and can hand multiple chunks to the driver routine which
    outputs the text; whereas putchar() only hands one char at a time to
    the driver - slowing thing down. -?

    > (See
    > Section 6.5.14; see alsohttp://www.c-faq.com/Question 20.13.)


    I've had a look and fail to see how Section 6.5.14
    http://c0x.coding-guidelines.com/6.5.14.html
    http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1124.pdf#page=101

    is relevant.

    -Albert
    , Oct 11, 2007
    #6
  7. Eric Sosman Guest

    Re: "multiple putchar()'s" versus "collect chars in char-array anduse puts()" - speed/efficiency

    wrote:
    > On Oct 11, 3:33 am, Eric Sosman <> wrote:
    >> wrote:
    >>> In terms of efficieny:
    >>> Is it better to use multiple putchar()'s after one another as one gets
    >>> to new char's
    >>> OR
    >>> is it better to collect the characters to a char-array first, and then
    >>> use puts() to print to screen

    >> The C Standard says next to nothing about efficiency, even
    >> though "efficiency" is one of the principal reasons people turn
    >> to C nowadays. However, in regard to the question you ask the
    >> Standard, unusually, offers an unequivocal answer: "Yes!"

    >
    > "Yes" to the first part (use multiple putchar()'s) OR "yes" to the
    > second part (collect and use puts()) ???
    > [...]
    >> (See
    >> Section 6.5.14; see alsohttp://www.c-faq.com/Question 20.13.)

    >
    > I've had a look and fail to see how Section 6.5.14
    > http://c0x.coding-guidelines.com/6.5.14.html
    > http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1124.pdf#page=101
    >
    > is relevant.


    It describes the result of the logical OR operator.
    In your case, the two propositions are opposites, so
    their OR is true, hence "Yes!"

    Once again, I commend Question 20.13 of the FAQ to
    your attention.

    --
    Eric Sosman
    lid
    Eric Sosman, Oct 11, 2007
    #7
  8. Re: "multiple putchar()'s" versus "collect chars in char-array and useputs()" - speed/efficiency

    wrote:
    >
    > On Oct 11, 3:33 am, Eric Sosman <> wrote:
    > > wrote:
    > > > In terms of efficieny:

    > >
    > > > Is it better to use multiple putchar()'s after one another as one gets
    > > > to new char's

    > >
    > > > OR

    > >
    > > > is it better to collect the characters to a char-array first, and then
    > > > use puts() to print to screen

    > >
    > > The C Standard says next to nothing about efficiency, even
    > > though "efficiency" is one of the principal reasons people turn
    > > to C nowadays. However, in regard to the question you ask the
    > > Standard, unusually, offers an unequivocal answer: "Yes!"

    >
    > "Yes" to the first part (use multiple putchar()'s) OR "yes" to the
    > second part (collect and use puts()) ???
    >
    > I suspect you mean "yes" to the 2nd part, since there puts() works at
    > a low level and can hand multiple chunks to the driver routine which
    > outputs the text; whereas putchar() only hands one char at a time to
    > the driver - slowing thing down. -?


    I suspect he meant "yes" to the entire statement. (As in, "yes,
    either it will be more efficient to do the former, or it will be
    more efficient to do the latter".) It was a way of saying there
    is no firm "using this method will be more efficient in all
    situations". In some cases, one will be "better", while in other
    cases, that same one is "worse".

    > > (See
    > > Section 6.5.14; see alsohttp://www.c-faq.com/Question 20.13.)

    >
    > I've had a look and fail to see how Section 6.5.14
    > http://c0x.coding-guidelines.com/6.5.14.html
    > http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1124.pdf#page=101
    >
    > is relevant.


    6.5.14 describes the logical OR operator. The statement "A or B" is
    true if either A or B is true. (You asked "is this better OR is that
    better?" Since one of those must be true, "A or B" must be true.)

    His reference to 6.5.14 confirms my original interpretation.

    Consider that, to many programmers, "do you know what time it is"
    requires a boolean response.

    Consider that, to a computer, "give me a list of people who live in
    New York and New Jersey" is likely to return a very short (if not
    empty) list.

    --
    +-------------------------+--------------------+-----------------------+
    | Kenneth J. Brody | www.hvcomputer.com | #include |
    | kenbrody/at\spamcop.net | www.fptech.com | <std_disclaimer.h> |
    +-------------------------+--------------------+-----------------------+
    Don't e-mail me at: <mailto:>
    Kenneth Brody, Oct 11, 2007
    #8
  9. On Thu, 11 Oct 2007 00:54:36 -0000, wrote:

    >In terms of efficieny:
    >
    >Is it better to use multiple putchar()'s after one another as one gets
    >to new char's
    >
    >OR
    >
    >is it better to collect the characters to a char-array first, and then
    >use puts() to print to screen
    >????


    It depends on how your system implements I/O. The various byte output
    functions are required to behave "as if" fputc was called for each
    character.

    If puts and putchar both actually do call fputc for each character and
    if putchar is a macro, then

    The putchar approach requires n calls to fputc.

    The puts approach requires the same n calls + one call to puts
    + the effort to build the array.

    putchar appears more efficient.

    If puts does its own I/O in a single block and if function calls are
    "expensive", then puts appears more efficient.

    Unless you are doing a ton of I/O, it would be better(tm) to use the
    approach that is more natural to whatever process you are performing.
    The execution cost will be insignificant compared to future
    maintenance costs when the program is updated.

    >
    >
    >
    >/******* ExampleA **********/
    >/**** collect chars and then call puts ****/
    >
    >char symbols[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
    > 'A', 'B', 'C', 'D', 'E', 'F'};
    >
    >#define uchar2hex(char_ptr, str_ptr) \
    > *str_ptr++ = symbols[((unsigned char)*char_ptr) >> 4]; \
    > *str_ptr++ = symbols[((unsigned char)*char_ptr++) & 0xF]; \
    > *str_ptr++ = ' ';
    >
    >{
    > int i;
    > char source[29] = "asdfasdfasdfasdfsadfasdfasdf";
    > char *src_ptr = source;
    > char dest[29];


    This is the wrong size for dest. Each input character requires three
    output characters. Once i gets to 10, you will overflow this array
    and enter the realm of undefined behavior.

    > char *dest_ptr = dest;
    >
    > for (i = 0; i < 29; i++) {
    > uchar2hex(src_ptr, dest_ptr);
    > }
    > *dest_ptr = '\0';
    > puts(dest);
    >}
    >
    >/********* ExampleB *************/
    >/***** putchar() as each new char is encountered ******/
    >
    >char symbols[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
    > 'A', 'B', 'C', 'D', 'E', 'F'};
    >
    >#define uchar2hex2(char_ptr, str_ptr) \
    > putchar(*str_ptr++ = symbols[((unsigned char)*char_ptr) >> 4]); \
    > putchar(*str_ptr++ = symbols[((unsigned char)*char_ptr++) & 0xF]); \
    > putchar(*str_ptr++ = ' ');


    Why are you storing the output characters anywhere?

    >
    >{
    > int i;
    > char source[29] = "asdfasdfasdfasdfsadfasdfasdf";
    > char *src_ptr = source;
    > char dest[29];


    Also too small.

    > char *dest_ptr = dest;
    >
    > for (i = 0; i < 29; i++) {
    > uchar2hex2(src_ptr, dest_ptr);
    > }
    > *dest_ptr = '\0';


    Since you output individual characters and not a string, why bother?

    >}



    Remove del for email
    Barry Schwarz, Oct 13, 2007
    #9
  10. SM Ryan Guest

    wrote:
    # In terms of efficieny:
    #
    # Is it better to use multiple putchar()'s after one another as one gets
    # to new char's
    #
    # OR
    #
    # is it better to collect the characters to a char-array first, and then
    # use puts() to print to screen
    # ????

    Whatever simplifies your code is best.

    --
    SM Ryan http://www.rawbw.com/~wyrmwif/
    Haven't you ever heard the customer is always right?
    SM Ryan, Oct 20, 2007
    #10
    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. Matthew Louden
    Replies:
    1
    Views:
    6,906
    Scott M.
    Oct 11, 2003
  2. Replies:
    9
    Views:
    448
    Michael Wojcik
    Jan 4, 2005
  3. Replies:
    9
    Views:
    345
    Jerry Coffin
    Jul 28, 2006
  4. Paul Butcher
    Replies:
    12
    Views:
    705
    Gary Wright
    Nov 28, 2007
  5. odigity

    perl hash speed and memory efficiency

    odigity, May 27, 2004, in forum: Perl Misc
    Replies:
    1
    Views:
    122
    Ben Morrow
    May 27, 2004
Loading...

Share This Page