function explanation

Discussion in 'C Programming' started by dominant, Sep 20, 2003.

  1. dominant

    dominant Guest

    What this function does?



    void test_function(char *s, char *t) {



    while(*s++=*t++)

    ;



    }


    --
    Posted via http://dbforums.com
    dominant, Sep 20, 2003
    #1
    1. Advertising

  2. dominant

    Mike Wahler Guest

    "dominant" <> wrote in message
    news:...
    >
    > What this function does?
    >
    >
    >
    > void test_function(char *s, char *t) {
    >
    >
    >
    > while(*s++=*t++)
    >
    > ;
    >
    >
    >
    > }
    >
    >
    > --
    > Posted via http://dbforums.com
    Mike Wahler, Sep 20, 2003
    #2
    1. Advertising

  3. dominant

    Mike Wahler Guest

    "dominant" <> wrote in message
    news:...
    >
    > What this function does?
    >
    >
    >
    > void test_function(char *s, char *t) {
    >
    >
    >
    > while(*s++=*t++)
    >
    > ;
    >
    >
    >
    > }


    strcpy()

    -Mike
    Mike Wahler, Sep 20, 2003
    #3
  4. "dominant" <> wrote in message
    news:...
    >
    > What this function does?
    >
    >
    >
    > void test_function(char *s, char *t) {
    >
    > while(*s++=*t++);


    Remember that the = operator returns the value that
    was assigned. Also remember that thew while loop
    terminates when the controlling expression returns
    0.

    Then consider strings in C. They consist of a bunch of
    characters followed by a null character. The null
    character has value 0.

    (Note that exactly when s and t are incremented is not
    a straightforward issue for many beginners so this is
    slightly informal, but is probably good enough for you)

    First of s and t are incremented, ie. they are made to
    point to the next char in the string they are pointing
    to. Then their old value is returned for the * operator
    to use. This means that value t was (since this is after
    the increment) pointing to is now assigned to the position
    s was pointing to. This value is then inspected by the while
    loop to see if this value is 0 or not. If it is non-zero then
    the loop goes again, but this time s and t are pointing
    to different positions. So when t is pointing to a null
    terminator, this value (aka 0) is assigned to *s and the while
    loop gets a 0 and terminates.

    The while loop can also be written like this:

    while(*s = *t)
    {
    t++;
    s++;
    }

    Note that the version you posted makes t potentially point
    outside the array it is pointing to[1]. This is however legal
    as the standard allows this to cater for the above idiom and
    friends. You are not allowed to dereference this pointer even
    if it is pointing somewhere legal.

    [1] It is actually pointing to elements in the array, but you get
    my drift.

    --
    Thomas.
    Thomas Stegen, Sep 20, 2003
    #4
  5. dominant

    Malcolm Guest

    "dominant" <> wrote in message
    >
    > void test_function(char *s, char *t)
    > while(*s++=*t++)
    > ;
    > }
    >

    This is terrible C style. The equals sign is not a equality comparison, as
    it looks like give the context, but an assignment. When the result of the
    assignment, *s, goes to zero, the loop will terminate. The semicolon
    indicates that it is an empty loop.
    The ++ operators increment the pointers, and are applied after the
    assignment takes place. This you wouldn't know if you didn't know C, but is
    idiomatic and therefore just acceptable.
    The combination of three quirky C features in one short loop makes this code
    very difficult to read and debug.
    Malcolm, Sep 21, 2003
    #5
  6. "Malcolm" <> wrote in message
    news:bkl25e$acd$...
    >
    > "dominant" <> wrote in message
    > >
    > > void test_function(char *s, char *t)
    > > while(*s++=*t++)
    > > ;
    > > }

    > The combination of three quirky C features in one short loop makes this

    code
    > very difficult to read and debug.
    >


    Given the fact that it is a well known and accepted idiom
    it is neither hard to read or hard to debug. First time I saw
    it it took me about 1 minute to figure out what this was
    doing.

    --
    Thomas.
    Thomas Stegen, Sep 22, 2003
    #6
  7. dominant

    pete Guest

    Thomas Stegen wrote:
    >
    > "Malcolm" <> wrote in message
    > news:bkl25e$acd$...
    > >
    > > "dominant" <> wrote in message


    [snip]
    > > > (char *s, char *t)
    > > > while(*s++=*t++)
    > > > ;
    > > > }


    > > The combination of three quirky C features
    > > in one short loop makes this code
    > > very difficult to read and debug.


    That code is taken directly from page 106, K&R2, section 5.5.

    > Given the fact that it is a well known and accepted idiom
    > it is neither hard to read or hard to debug.


    "... the idiom should be mastered,
    because you will see it frequently in C programs."

    --
    pete
    pete, Sep 22, 2003
    #7
  8. "pete" <> wrote in message
    news:...
    ....
    > > > > (char *s, char *t)
    > > > > while(*s++=*t++)
    > > > > ;

    >
    > "... the idiom should be mastered,
    > because you will see it frequently in C programs."


    I can't speak for anyone else, but it was the extraordinary succinctness of
    this paradigm that drew me to C in the first place.

    Although, I've since been told that for many architectures, the following is
    more likely to generate efficient machine code...

    if (*s = *t)
    while (*++s = *++t)
    ;

    I guess learning 68000 assembler before I saw C was both an advantage and
    disadvantage.

    --
    Peter
    Peter Nilsson, Sep 22, 2003
    #8
  9. dominant

    Malcolm Guest

    "Peter Nilsson" <> wrote in message
    >
    > > > > > (char *s, char *t)
    > > > > > while(*s++=*t++)
    > > > > > ;

    > >

    > I can't speak for anyone else, but it was the extraordinary succinctness >

    of this paradigm that drew me to C in the first place.
    >

    It shouldn't do. Programs are designed to present a series of instructions
    to a computer, but they must also present code to another human programmer.
    Generally the cost of a programmmer's time reading and understanding code
    far exceeds the cost of computer time executing it. There are exceptions,
    such as the inner loops of time-critical programs like games, but as a rule
    code should be written so that it is as easy as possible to understand.
    You can assume that your reader knows the C basics, and knows how to
    program, but you shouldn't necessarily assume that he is comfortable with C
    arcana. In particular constructions such as
    while(a = b)
    which suggest the wrong meaning should be avoided.
    Malcolm, Sep 25, 2003
    #9
  10. "Malcolm" <> wrote in message news:<bkvrca$8lf$>...
    > "Peter Nilsson" <> wrote in message
    > >
    > > > > > > (char *s, char *t)
    > > > > > > while(*s++=*t++)
    > > > > > > ;
    > > >

    > > I can't speak for anyone else, but it was the extraordinary succinctness
    > > of this paradigm that drew me to C in the first place.

    >
    > It shouldn't do. Programs are designed to present a series of instructions
    > to a computer, but they must also present code to another human programmer.
    > Generally the cost of a programmmer's time reading and understanding code
    > far exceeds the cost of computer time executing it.


    The 'understanding' you speak of is an aquired skill and not something
    easily quantifiable. Languages like Lisp and Forth are quite often far
    from obvious to the lay programmer, but they both offer aesthetic
    clarity and elegance in constructs that aren't easily understood by
    people for whom the languages haven't 'clicked' yet.

    Any C programmer who has difficulty understanding the above
    construction should not be let anywhere near anything even remotely
    critical. Programs should be written with clarity in mind, but the
    whole point of language development is to encapsulate paradigms with
    clean syntax.

    I've seen people use constructs like...

    while (...yadda...)
    {
    continue;
    }

    It's my personal opinion obviously, but arguments stating that the
    presence of the last three lines in place of a semi-colon aids
    readability are an insult to the intelligence of moderately competent
    C programmers.

    > There are exceptions,
    > such as the inner loops of time-critical programs like games, but as a rule
    > code should be written so that it is as easy as possible to understand.


    What is difficult to understand about...?

    while (*s++ = *t++)
    ;

    > You can assume that your reader knows the C basics,


    No. If you're talking about non toy programs, you can assume that the
    reader knows more than the basics. If you don't then you must be
    anticipating your code being modified and subsequently distributed by
    people not really qualified to so.

    > and knows how to
    > program, but you shouldn't necessarily assume that he is comfortable with C
    > arcana. In particular constructions such as
    > while(a = b)
    > which suggest the wrong meaning should be avoided.


    I would say 'In contrast...' The meaning of original construct is IMHO
    self evident.

    --
    Peter
    Peter Nilsson, Sep 26, 2003
    #10
  11. On 25 Sep 2003, Peter Nilsson wrote:

    > What is difficult to understand about...?
    >
    > while (*s++ = *t++)
    > ;


    First, there's an off by one error. Second, it doesn't terminate the
    destination string.

    ;)
    Jarno A Wuolijoki, Sep 26, 2003
    #11
  12. dominant

    goose Guest

    "Thomas Stegen" <> wrote in message news:<3f6eb34d$>...
    > "Malcolm" <> wrote in message
    > news:bkl25e$acd$...
    > >
    > > "dominant" <> wrote in message
    > > >
    > > > void test_function(char *s, char *t)
    > > > while(*s++=*t++)
    > > > ;
    > > > }

    > > The combination of three quirky C features in one short loop makes this

    > code
    > > very difficult to read and debug.
    > >

    >
    > Given the fact that it is a well known and accepted idiom
    > it is neither hard to read or hard to debug. First time I saw
    > it it took me about 1 minute to figure out what this was
    > doing.


    also, the pattern of "while (*src_ptr++ = *dst_ptr++)" is
    fairly common, and I personally find it intuitive these days
    when looking at code. it tells you (or rather, it /should/) the
    intent of the programmer without needing a single comment.

    goose,
    goose, Sep 26, 2003
    #12
  13. dominant

    CBFalconer Guest

    Jarno A Wuolijoki wrote:
    > On 25 Sep 2003, Peter Nilsson wrote:
    >
    > > What is difficult to understand about...?
    > >
    > > while (*s++ = *t++)
    > > ;

    >
    > First, there's an off by one error. Second, it doesn't terminate
    > the destination string.


    No there isn't (an error). Yes it does (terminate). All assuming
    the source is a legitimate string and source and destination do
    not overlap.

    --
    Chuck F () ()
    Available for consulting/temporary embedded and systems.
    <http://cbfalconer.home.att.net> USE worldnet address!
    CBFalconer, Sep 26, 2003
    #13
  14. CBFalconer <> spoke thus:

    >> > while (*s++ = *t++)
    >> > ;


    > No there isn't (an error). Yes it does (terminate). All assuming
    > the source is a legitimate string and source and destination do
    > not overlap.


    And also that s has space for strlen(t)+1 characters.

    --
    Christopher Benson-Manica | Jumonji giri, for honour.
    ataru(at)cyberspace.org |
    Christopher Benson-Manica, Sep 26, 2003
    #14
  15. dominant

    John Bode Guest

    Jarno A Wuolijoki <> wrote in message news:<>...
    > On 25 Sep 2003, Peter Nilsson wrote:
    >
    > > What is difficult to understand about...?
    > >
    > > while (*s++ = *t++)
    > > ;

    >
    > First, there's an off by one error.


    Where?

    > Second, it doesn't terminate the destination string.
    >
    > ;)


    Only if the source string isn't terminated, either.
    John Bode, Sep 26, 2003
    #15
  16. On Fri, 26 Sep 2003, CBFalconer wrote:

    > > > What is difficult to understand about...?
    > > >
    > > > while (*s++ = *t++)
    > > > ;

    > >
    > > First, there's an off by one error. Second, it doesn't terminate
    > > the destination string.

    >
    > No there isn't (an error). Yes it does (terminate).


    And that's supposed to be easy to understand?


    *t++; /* "get()" */
    *s++=x; /* "put(x)" */
    *s++=*t++; /* "put(get())" */

    while (tmp=*t++) *s++=tmp;
    /* "as long as we can get data, append it to s" */
    *s=0;
    /* terminate s; */

    while (*t) *s++=*t++;
    *s=0;
    /* "as long as there's data, copy it." */

    while (*s++=*t++) ;
    /* "as long as we have copied nonzero data, do nothing. perform extra
    copy as a side effect of embedding it in the test" */

    (of course if you interpret "*s++=*t++" as a routine which returns 0
    when it has finished it makes a whole lot more sense..)
    Jarno A Wuolijoki, Sep 26, 2003
    #16
  17. Jarno A Wuolijoki <> wrote:

    >On Fri, 26 Sep 2003, CBFalconer wrote:
    >
    >> > > What is difficult to understand about...?
    >> > >
    >> > > while (*s++ = *t++)
    >> > > ;
    >> >
    >> > First, there's an off by one error. Second, it doesn't terminate
    >> > the destination string.

    >>
    >> No there isn't (an error). Yes it does (terminate).

    >
    >And that's supposed to be easy to understand?


    Yes. :)

    <SNIP>

    Irrwahn
    --
    ERROR 103: Dead mouse in hard drive.
    Irrwahn Grausewitz, Sep 26, 2003
    #17
  18. dominant

    pete Guest

    CBFalconer wrote:
    >
    > Jarno A Wuolijoki wrote:
    > > On 25 Sep 2003, Peter Nilsson wrote:
    > >
    > > > What is difficult to understand about...?
    > > >
    > > > while (*s++ = *t++)
    > > > ;

    > >
    > > First, there's an off by one error. Second, it doesn't terminate
    > > the destination string.

    >
    > No there isn't (an error). Yes it does (terminate). All assuming
    > the source is a legitimate string and source and destination do
    > not overlap.


    It depends on how they overlap.

    --
    pete
    pete, Sep 27, 2003
    #18
  19. dominant

    Malcolm Guest

    "Jarno A Wuolijoki" <> wrote in message
    > On Fri, 26 Sep 2003, CBFalconer wrote:
    >
    > > > > What is difficult to understand about...?
    > > > >
    > > > > while (*s++ = *t++)
    > > > > ;
    > > >
    > > > First, there's an off by one error. Second, it doesn't terminate
    > > > the destination string.

    > >
    > > No there isn't (an error). Yes it does (terminate).

    >
    > And that's supposed to be easy to understand?
    >

    Exactly. We have a construct that is supposedly "easy to understand",
    perfectly acceptable, idiomatic C, and first a newbie posts with "what does
    this do" and then another poster mistakes it for a bug.

    Most of C is basically the same as any other programming language. Someone
    who knows another language will easily understand

    int x = 0;

    he will also quickly get

    for(i=0;i<100;i++)

    even though ++ is a pure C idiom.

    When it comes to pointers, he has some learning to do. He can quickly pick
    up that * is the indirection operator. A bit more difficult is that
    *ptr++ increments ptr, rather than *ptr, despite the fact that the ++ is
    applied last.

    However when we come to

    while(*s++ = *t++);

    it is a bridge too far for our experienced programmer who only knows a bit
    of C. Unless you know, it is deeply counter intutive that = in this context
    means "assign" rather than "compare". If he's lucky he will remember the
    pointer incrementing and dereference rules, but only just, and this will
    make him uncomfortable and unfamiliar with the whole expression. Finally,
    using a semi-colon to denote an empty loop is also something that has few
    parallels in other languages, and looks like a syntax error.

    In short, this expression will make the code harder to read and is likely to
    cause trouble. Even an experienced C programmer, though he will not
    misinterpret it, will probably take longer to read and understand the
    expression and verify that it is correct. This is particularly the case if
    it is embedded in a list of other expressions which are also
    counter-intutive and difficult to understand.
    Malcolm, Sep 28, 2003
    #19
  20. dominant

    pete Guest

    Malcolm wrote:

    > Even an experienced C programmer, though he will not
    > misinterpret it, will probably take longer to read and understand the
    > expression and verify that it is correct.


    "... the idiom should be mastered,
    because you will see it frequently in C programs."

    Mastering the idiom means, that you will recognize it,
    and know at a glance, what it means.

    If you have not mastered it, then it may be tough.
    But the mastery that particular idiom, is more common than not,
    among experienced C programmers.

    A few snippets for you:

    void copyarray(e_type *s1, e_type *s2, size_t nmemb)
    {
    while (nmemb--) {
    *s1++ = *s2++;
    }
    }

    char *squeeze(char *s1, const char *s2)
    {
    char const* p2;
    char *const p1 = s1;

    for (p2 = strtok(s1, s2); p2; p2 = strtok( 0, s2)) {
    while (*p2) {
    *s1++ = *p2++;
    }
    }

    *s1 = '\0';
    return p1;
    }

    static void merge(e_type *base, e_type *buffer, size_t nmemb)
    {
    if (nmemb > SMALL_MERGE) {
    size_t const half = nmemb / 2;
    e_type *const middle = base + half;
    e_type *const after_buffer = buffer + half;
    e_type *const after_array = base + nmemb;
    e_type *mid_ptr = middle;

    merge(base, buffer, half);
    merge(middle, buffer, nmemb - half);
    while (GTE(middle, base) && middle != base) {
    ++base;
    }
    buffer = after_buffer;
    while (base != mid_ptr) {
    *--buffer = *--mid_ptr;
    }
    mid_ptr = middle;
    while (middle != base) {
    *base++ = GT(buffer, mid_ptr) ? *mid_ptr++ : *buffer++;
    }
    while (after_buffer != buffer && after_array != mid_ptr) {
    *base++ = GT(buffer, mid_ptr) ? *mid_ptr++ : *buffer++;
    }
    while (after_buffer != buffer) {
    *base++ = *buffer++;
    }
    } else {
    si_sort(base, nmemb);
    }
    }

    --
    pete
    pete, Sep 29, 2003
    #20
    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. Mariusz

    explanation

    Mariusz, Jan 12, 2004, in forum: VHDL
    Replies:
    1
    Views:
    594
    tbx135
    Jan 13, 2004
  2. Kaladhaur Palaniappa

    Need Explanation

    Kaladhaur Palaniappa, Aug 7, 2003, in forum: Perl
    Replies:
    0
    Views:
    1,007
    Kaladhaur Palaniappa
    Aug 7, 2003
  3. Benjie Fallar

    tracing output explanation

    Benjie Fallar, Jul 15, 2003, in forum: ASP .Net
    Replies:
    0
    Views:
    360
    Benjie Fallar
    Jul 15, 2003
  4. George Ter-Saakov

    Do you have an explanation for this?

    George Ter-Saakov, Apr 29, 2004, in forum: ASP .Net
    Replies:
    1
    Views:
    589
    Pravin A. Sable
    Apr 30, 2004
  5. Onix
    Replies:
    3
    Views:
    265
Loading...

Share This Page