Trick Question

This is a discussion on Trick Question within the C Programming forums, part of the General Programming Boards category; Do these loops do the same thing, and if so, what do they do?: Code: /* assuming |str| >= 1 ...

  1. #1
    Registered Abuser
    Join Date
    Jun 2006
    Location
    Toronto
    Posts
    591

    Trick Question

    Do these loops do the same thing, and if so, what do they do?:
    Code:
    /* assuming |str| >= 1 */
    /*1*/ char *p = str; while( (*p = *++p) != '\0' ) ;
    /*2*/ char *p = str; while( (*p = *(p++ + 1)) != '\0' ) ;
    /*3*/ int i = 0; while( (str[i] = str[++i]) != '\0' ) ;
    /*4*/ int i; for( i = 0; str[i] != '\0'; str[i] = str[++i] ) ;
    Maybe it's incredibly obvious, and maybe I should stop programming at 4 in the morning...

  2. #2
    The larch
    Join Date
    May 2006
    Posts
    3,573
    All these versions are based on undefined behaviour and could do anything.

    Why do some people think x = ++y + y++ is bad? (A C++ link but applies to C too.)
    Last edited by anon; 04-16-2009 at 07:06 AM.
    I might be wrong.

    Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.
    Quoted more than 1000 times (I hope).

  3. #3
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    21,794
    I think they all do the same thing, i.e., they do something that results in undefined behaviour.
    C + C++ Compiler: MinGW port of GCC
    Version Control System: Bazaar

    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  4. #4
    and the hat of sweating
    Join Date
    Aug 2007
    Location
    Toronto, ON
    Posts
    3,545
    Quote Originally Posted by anon View Post
    All these versions are based on undefined behaviour and could do anything.

    Why do some people think x = ++y + y++ is bad? (A C++ link but applies to C too.)
    Are you sure it's undefined?
    I only see one pre or post increment per statement.
    "I am probably the laziest programmer on the planet, a fact with which anyone who has ever seen my code will agree." - esbo, 11/15/2008

    "the internet is a scary place to be thats why i dont use it much." - billet, 03/17/2010

  5. #5
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    21,794
    Quote Originally Posted by cpjust
    I only see one pre or post increment per statement.
    But you also see another occurrence of the variable involved in the increment, hence the variable is read twice and yet modified between two sequence points.
    C + C++ Compiler: MinGW port of GCC
    Version Control System: Bazaar

    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  6. #6
    and the hat of sweating
    Join Date
    Aug 2007
    Location
    Toronto, ON
    Posts
    3,545
    Quote Originally Posted by laserlight View Post
    But you also see another occurrence of the variable involved in the increment, hence the variable is read twice and yet modified between two sequence points.
    Oh, duh! Of course... Now I see it.
    (*p = *++p) is doing a pre-increment, so it's undefined behavior (although I would read it the same as: ++p; *p = *p )

    but what about post-increment?
    (*p = *(p++ + 1))
    Would that still be undefined behavior?
    I think it's pretty clear that it's saying: *p = *(p + 1); ++p;
    "I am probably the laziest programmer on the planet, a fact with which anyone who has ever seen my code will agree." - esbo, 11/15/2008

    "the internet is a scary place to be thats why i dont use it much." - billet, 03/17/2010

  7. #7
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    21,794
    Quote Originally Posted by cpjust
    but what about post-increment?
    (*p = *(p++ + 1))
    Would that still be undefined behavior?
    Yes, presumably because the post-increment takes effect before the next sequence point. In fact, one of the examples of undefined behaviour provided by the C standard is:
    Code:
    a[i++] = i;
    C + C++ Compiler: MinGW port of GCC
    Version Control System: Bazaar

    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  8. #8
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    But it could be:
    Code:
    *p = {*(p + 1), ++p};
    where the braced expression is computed before *p = is stored. This would be the case on a PDP-11 (or VAX, 68K) architecture, where you would get this:
    Code:
    mov p, r0
    mov 1(r0)+, r1
    mov r1, (r0)
    [I'm not 100% sure that is actually VALID PDP-11 code, but you can probably see the intent, and whilst THIS particular case may not be valid code, it would be fairly complicated to describe the exact cases which ALL compilers CAN generate valid code for, and the list of expressions which are NOT possible to generate valid code for with such optimization enabled - it is much simpler to state "if you modify the variable in an expression, it must not be used elsewhere too"].

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  9. #9
    and the hat of sweating
    Join Date
    Aug 2007
    Location
    Toronto, ON
    Posts
    3,545
    Quote Originally Posted by laserlight View Post
    Yes, presumably because the post-increment takes effect before the next sequence point. In fact, one of the examples of undefined behaviour provided by the C standard is:
    Code:
    a[i++] = i;
    I'm just having a hard time understanding why (other than because the standard say so) that example would be undefined, since the post-increment happens after the statement is finished...
    "I am probably the laziest programmer on the planet, a fact with which anyone who has ever seen my code will agree." - esbo, 11/15/2008

    "the internet is a scary place to be thats why i dont use it much." - billet, 03/17/2010

  10. #10
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by cpjust View Post
    I'm just having a hard time understanding why (other than because the standard say so) that example would be undefined, since the post-increment happens after the statement is finished...
    Again, in 68k, you could implement that as something like this (this is NOT valid 68K assembler, but it shows the OPPURTUNITY for this to be done this way, and there is nothing saying there isn't a version of processor somewhere that supports this sort of thing)
    Code:
       lea r1, a(r0)+
       mov r0, (r1)
    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  11. #11
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    21,794
    Quote Originally Posted by cpjust
    I'm just having a hard time understanding why (other than because the standard say so) that example would be undefined, since the post-increment happens after the statement is finished...
    Maybe we can reason this way:
    Code:
    a[i++] = x;
    is effectively equivalent to:
    Code:
    T temp = i++;
    a[temp] = x;
    Therefore:
    Code:
    a[i++] = i;
    can be written as:
    Code:
    T temp = i++;
    a[temp] = i;
    You can disagree, but the compiler can point out that by the language rules i will not be read second time before the next sequence point, so surely the transformation is correct.
    C + C++ Compiler: MinGW port of GCC
    Version Control System: Bazaar

    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  12. #12
    and the hat of sweating
    Join Date
    Aug 2007
    Location
    Toronto, ON
    Posts
    3,545
    Quote Originally Posted by laserlight View Post
    Maybe we can reason this way:
    Code:
    a[i++] = x;
    is effectively equivalent to:
    Code:
    T temp = i++;
    a[temp] = x;
    Therefore:
    Code:
    a[i++] = i;
    can be written as:
    Code:
    T temp = i++;
    a[temp] = i;
    You can disagree, but the compiler can point out that by the language rules i will not be read second time before the next sequence point, so surely the transformation is correct.
    But doesn't that defeat the whole point of the post-increment? Otherwise it's not doing the "post" part of the increment.
    "I am probably the laziest programmer on the planet, a fact with which anyone who has ever seen my code will agree." - esbo, 11/15/2008

    "the internet is a scary place to be thats why i dont use it much." - billet, 03/17/2010

  13. #13
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by cpjust View Post
    But doesn't that defeat the whole point of the post-increment? Otherwise it's not doing the "post" part of the increment.
    It is POST getting the value of i for the index - which is what the standard says anything about - it does specifically say that "it will happen before the next sequence point", but nothing about where within the sequence point it is actually being done. As I have tried to show in the small snippets of 68K/PDP-11 (or similar), it is POSSIBLE to have ONE instruction that does fetch and increment at the same time.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  14. #14
    and the hat of sweating
    Join Date
    Aug 2007
    Location
    Toronto, ON
    Posts
    3,545
    Quote Originally Posted by matsp View Post
    As I have tried to show in the small snippets of 68K/PDP-11 (or similar), it is POSSIBLE to have ONE instruction that does fetch and increment at the same time.
    Ah, so that's what that does... I'm not very Assembly literate.
    "I am probably the laziest programmer on the planet, a fact with which anyone who has ever seen my code will agree." - esbo, 11/15/2008

    "the internet is a scary place to be thats why i dont use it much." - billet, 03/17/2010

  15. #15
    Registered Abuser
    Join Date
    Jun 2006
    Location
    Toronto
    Posts
    591
    Thanks for clearing that up all. I'm going to need to re-read this a couple times to fully understand why the post-increment results in undefined behaviour.

Page 1 of 2 12 LastLast
Popular pages Recent additions subscribe to a feed

Similar Threads

  1. The Meaning of Life: A Trick Question?
    By chix/w/guns in forum A Brief History of Cprogramming.com
    Replies: 14
    Last Post: 07-12-2004, 07:53 PM
  2. Question about pointers #2
    By maxhavoc in forum C++ Programming
    Replies: 28
    Last Post: 06-21-2004, 12:52 PM
  3. Question...
    By TechWins in forum A Brief History of Cprogramming.com
    Replies: 16
    Last Post: 07-28-2003, 09:47 PM
  4. Question about linked lists.
    By cheeisme123 in forum C++ Programming
    Replies: 6
    Last Post: 02-25-2003, 12:36 PM
  5. Question, question!
    By oskilian in forum A Brief History of Cprogramming.com
    Replies: 5
    Last Post: 12-24-2001, 12:47 AM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21