🔒 Locked
c++ syntax
Advertisement
Original Post
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
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.
The actual behavior is the reverse of what you claimed it was; it increments index then tests a plane with itself.
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]
I would probably do it like so:
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.
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.
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).
Quote:
Original post by Anonymous Poster
It could be a for loop, but as mentioned by gumpy macdrunkenQuote:(nice edit)
...your code looks like an example of ... optimization...
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
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 11218No 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]
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:
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.
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.
Advertisement