Skip to main content
gamedev.net
🔒 Locked

c++ syntax

Started by Quak May 26, 2006 at 8:59 AM 13 replies 1.1k views
Original Post
Quak
Quak
Hi, I use this code for a loop: do{ //code... } while( node[index].plane == node[(index = node[index].next)].plane); I think my intention is obvious: I want to compare the plane value to the plane value of the next node in the list and at the same time store the next index in index. However, the code seems to work like this: node[index].plane == node[index].plane; index = node[index].next; So the condition is always true. What's wrong with this syntax ? Thanks for help! Quak
Deyja
Deyja
The syntax is correct. Unfortunatly, the behavior is undefined. operator== is nothing more than a function call, and the order of evaluation of arguments in a function call is undefined. In your case, the right side is being evaluated first. The meaning of the left side is different depending on the order of evaluation.

The actual behavior is the reverse of what you claimed it was; it increments index then tests a plane with itself.
rip-off
rip-off
Quote:

I think my intention is obvious...


I think you're wrong. [grin]

Simplify the code:

int oldindex;int index = ...;do{   // stuff   oldindex = index;   index = node[index.next];}while( node[oldindex].plane == node[index].plane);


Maybe that will work?
gumpy
gumpy
Quote:
Original post by rip-off
Simplify the code

exactly. keep code simple and readable. your code looks like an example of premature optimization. years ago writing confusing code in the name of optimization made sense, but modern compilers solved the need for that. see the doom source code for examples of what not to do anymore. [lol]
This space for rent.
Quak
Quak
Thank for your help. The "simple" solution seems to be the only choice even though it looks ugly to me somehow ;)
Anon Mike
Anon Mike
I would probably do it like so:
index = ...;plane = node[index].plane;do{  ...;  index = node[index].next;}while (node[index].plane == plane);

Be careful you don't walk off the end of the node array during all this. Nobody's code is checking for that.

In C++ you could probably do a combination of find_if and for_each instead. There may be something similiar that does it more directly but I can't think of it offhand.
-Mike
NotAYakk
NotAYakk
This looks like a for loop to me. =)

index = ...{for (  PlaneType plane = node[index].plane;  node[index].plane == plane;  index = node[index].next) {  ...}}


UnPatented DoubleBrace(tm) technology keeps evil non-standard scope of for() loop variables from leaking.
medevilenemy
medevilenemy
a do while is not actually quicker, it is just meant to be used for a different purpose... anyway, in my experience it is almost always better to use a for loop when you can. This is mainly because a properly written for loop will not infinitely loop (unless you tell it to) and will not cause an out-of bounds error (unless you mess it up).
There was a saying we had in college: Those who walk into the engineering building are never quite the same when they walk out.
Enigma
Enigma
Quote:
Original post by Anonymous Poster
It could be a for loop, but as mentioned by gumpy macdrunken
Quote:
...your code looks like an example of ... optimization...
(nice edit)

A do while is a quicker loop. Time the different loops yourself while,do while and for.

FUD.

#include <cstddef>typedef int PlaneType;struct Node{	PlaneType plane;	std::size_t next;};int main(){	Node node[4] =	{		{0, 1},		{0, 2},		{0, 3},		{1, 0}	};	int accumulator = 0;#if defined(PP_DO_WHILE)	std::size_t index = 0;	PlaneType plane = node[index].plane;	do	{		accumulator += index;		index = node[index].next;	} while (node[index].plane == plane);#else	std::size_t index = 0;	for (PlaneType plane = node[index].plane; node[index].plane == plane; index = node[index].next)	{		accumulator += index;	}#endif	return accumulator;}

 With PP_DO_WHILE defined                                                                Without PP_DO_WHILE defined; Listing generated by Microsoft (R) Optimizing Compiler Version 14.00.50727.42         ; Listing generated by Microsoft (R) Optimizing Compiler Version 14.00.50727.42         TITLE  C:\Paul\tmp\forvsdowhile.cpp                                                     TITLE  C:\Paul\tmp\forvsdowhile.cpp        .686P                                                                                   .686P        .XMM                                                                                    .XMM        include listing.inc                                                                     include listing.inc        .model  flat                                                                            .model  flatINCLUDELIB LIBCMT                                                                       INCLUDELIB LIBCMTINCLUDELIB OLDNAMES                                                                     INCLUDELIB OLDNAMESPUBLIC  _main                                                                           PUBLIC  _main; Function compile flags: /Ogtpy                                                        ; Function compile flags: /Ogtpy;       COMDAT _main                                                                    ;       COMDAT _main_TEXT   SEGMENT                                                                         _TEXT   SEGMENT_node$ = -32                                            ; size = 32                        _node$ = -32                                         ; size = 32_main   PROC                                            ; COMDAT                        _main   PROC                                            ; COMDAT; File c:\paul\tmp\forvsdowhile.cpp                                                     ; File c:\paul\tmp\forvsdowhile.cpp; Line 14                                                                               ; Line 14        sub     esp, 32                                 ; 00000020H                             sub     esp, 32                                 ; 00000020H; Line 17                                                                               ; Line 17        mov     eax, 1                                                                          mov     eax, 1        push    esi                                                                             push    esi        xor     esi, esi                                                                        xor     esi, esi        mov     DWORD PTR _node$[esp+40], eax                                                   mov     DWORD PTR _node$[esp+40], eax; Line 20                                                                               ; Line 20        mov     DWORD PTR _node$[esp+60], eax                                                   mov     DWORD PTR _node$[esp+60], eax; Line 22                                                                               ; Line 22        xor     eax, eax                                                                        xor     eax, eax; Line 26                                                                               ; Line 36        xor     ecx, ecx                                                                        xor     ecx, ecx        mov     DWORD PTR _node$[esp+36], esi                                                   mov     DWORD PTR _node$[esp+36], esi        mov     DWORD PTR _node$[esp+44], esi                                                   mov     DWORD PTR _node$[esp+44], esi        mov     DWORD PTR _node$[esp+48], 2                                                     mov     DWORD PTR _node$[esp+48], 2        mov     DWORD PTR _node$[esp+52], esi                                                   mov     DWORD PTR _node$[esp+52], esi        mov     DWORD PTR _node$[esp+56], 3                                                     mov     DWORD PTR _node$[esp+56], 3        mov     DWORD PTR _node$[esp+64], esi                                                   mov     DWORD PTR _node$[esp+64], esi; Line 32                                                                               ; Line 37        xor     edx, edx                                                                        xor     edx, edx        npad    7                                                                               npad    7$LL3@main:                                                                              $LL3@main:        add     eax, ecx                                                                ; Line 39        mov     ecx, DWORD PTR _node$[esp+edx+40]                                               add     eax, ecx        lea     edx, DWORD PTR [ecx*8]                                                          mov     ecx, DWORD PTR _node$[esp+edx+40]        cmp     DWORD PTR _node$[esp+edx+36], esi                                               lea     edx, DWORD PTR [ecx*8]        je      SHORT $LL3@main                                                                 cmp     DWORD PTR _node$[esp+edx+36], esi        pop     esi                                                                             je      SHORT $LL3@main; Line 45                                                                                       pop     esi        add     esp, 32                                 ; 00000020H                     ; Line 45        ret     0                                                                               add     esp, 32                                 ; 00000020H_main   ENDP                                                                                    ret     0_TEXT   ENDS                                                                            _main   ENDPEND                                                                                     _TEXT   ENDS                                                                                        END

Σnigma
rip-off
rip-off
Quote:

A do while is a quicker loop. Time the different loops yourself while,do while and for.

Is that so? I cannot reproduce this.

A do while loop is not 100% a while or for loop, as there is an additional test done just before the loop is entered. I have included both versions, just for fun. Also 3 different for loops, just to see what happened, I figured one of them should match the way other loops are output.

Here are a few versions of the same loop:

const long NUM = 100000000L;int main( int argc, char **argv ){    Uint32 time;    Uint32 for1=0, for2=0, for3=0, while1=0, do1=0, do2=0;    for( int i = 0 ; i < 100 ; ++i )    {        time = SDL_GetTicks();        {            for( long i = 0 ; i < NUM ; ++i )            {            }        }        for1 += SDL_GetTicks() - time;        time = SDL_GetTicks();        {            long i = 0;            for( ; i < NUM ; ++i )            {            }        }        for2 += SDL_GetTicks() - time;        time = SDL_GetTicks();        {            long i;            for( i = 0; i < NUM ; ++i )            {            }        }        for3 += SDL_GetTicks() - time;        time = SDL_GetTicks();        {            long i = 0;            while( i < NUM )            {                ++i;            }        }        while1 += SDL_GetTicks() - time;        time = SDL_GetTicks();        {            long i = 0;            do            {                ++i;            }while( i < NUM );        }        do1 += SDL_GetTicks() - time;        time = SDL_GetTicks();        {            long i = 0;            if( i < NUM )            {                do                {                    ++i;                }while( i < NUM );            }        }        do2 += SDL_GetTicks() - time;    }    cout << "for(li=0) time was "  << for1 << std::endl;    cout << "li=0 for() time was "  << for2 << std::endl;    cout << "li for(i=0) time was "  << for3 << std::endl;    cout << "while() time was " << while1 << std::endl;    cout << "do() time was "  << do1 << std::endl;    cout << "if()... do() time was "  << do2 << std::endl;    return 0;}

Results:

for(li=0) time was 11115li=0 for() time was 11216li for(i=0) time was 11084while() time was 11225do() time was 11161if()... do() time was 11218


No matter what the results are, I'm not advocating that we all use version 3 (or whichever one wins out in any given test) of the for loop from now on, all I am saying is you cannot treat your statement as truth for all compilers ( this was done using gcc, btw ).

The difference was only ~1% which (considering you got different results ) is not worth fighting over.

IMO, the right loop for the job. I use for loops 99% of the time. I believe that using do...while loops add confusion to your source for no reason.

[edit: enigmas example is better. If I knew assembly I might have tried the same trick, but I've never needed to get my asm from my compiler [smile]]
[edit #2: I quoted the wrong thing...]


[Edited by - rip-off on May 26, 2006 7:30:03 PM]
NotAYakk
NotAYakk
A do-while loop does the following:
1> It tests nothing at the start of the loop.
2> Every later loop it checks the while condition once.

A for-loop does the following:
1> It runs the "startup" statement at the start of the loop (optionally empty).
2> It tests the loop condition at the start of the loop.
3> It runs the increment operation and tests the loop-condition on every subsiquent loop.

So the do-while can at most save one loop condition test.

Practically, you can emulate a do-while loop with a for loop as follows:
{for(bool condition = true; condition; condition = (do-while-loop-condition) ) {  // ... body of loop}}


However, the difference between a naive for and do-while loop is at most a single loop-condition test.

Unless your code is being run on a per-pixel basis, a single loop-condition test doesn't matter. And if it is being run on a per-pixel basis, what the hell are you doing running any kind of loop on a per-pixel basis?

Write your code clean and readable, and optimize after you find a performance bottleneck.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.