Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. Other Discussions
  3. Clever Code
  4. Evil for loop

Evil for loop

Scheduled Pinned Locked Moved Clever Code
12 Posts 9 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • A Offline
    A Offline
    Alois Kraus
    wrote on last edited by
    #1

    I did some refactoring of some older code and came across this snippet: std::string str("This is a test str"); for(int i=str.length()-1;i>=0;i--) { printf("Examining char %d",i); } The compiler complained about this with a warning: warning C4267: 'initializing' : conversion from 'size_t' to 'int', possible loss of data Being a fan of zero compiler warnings I did give him what he wanted and changed the type of i from int to size_t. Ok it compiles now without any warnings but this change broke many applications during runtime. I was the bad guy of the week because this change was made in a low level library.

    R P N M Z 6 Replies Last reply
    0
    • A Alois Kraus

      I did some refactoring of some older code and came across this snippet: std::string str("This is a test str"); for(int i=str.length()-1;i>=0;i--) { printf("Examining char %d",i); } The compiler complained about this with a warning: warning C4267: 'initializing' : conversion from 'size_t' to 'int', possible loss of data Being a fan of zero compiler warnings I did give him what he wanted and changed the type of i from int to size_t. Ok it compiles now without any warnings but this change broke many applications during runtime. I was the bad guy of the week because this change was made in a low level library.

      R Offline
      R Offline
      Rob Graham
      wrote on last edited by
      #2

      NEVER refactor without unit tests...

      A 1 Reply Last reply
      0
      • A Alois Kraus

        I did some refactoring of some older code and came across this snippet: std::string str("This is a test str"); for(int i=str.length()-1;i>=0;i--) { printf("Examining char %d",i); } The compiler complained about this with a warning: warning C4267: 'initializing' : conversion from 'size_t' to 'int', possible loss of data Being a fan of zero compiler warnings I did give him what he wanted and changed the type of i from int to size_t. Ok it compiles now without any warnings but this change broke many applications during runtime. I was the bad guy of the week because this change was made in a low level library.

        P Offline
        P Offline
        PJ Arends
        wrote on last edited by
        #3

        C4267 is one of those 64bit compatability warnings. size_t is an unsigned int on Win32 but it is an unsigned __int64 on Win64. It used to be that sizeof(int) was OS dependant (2 bytes on Win16, 4 bytes on Win32) but from now on sizeof(int) is fixed at 4 bytes and sizeof(size_t) is variable depending on the OS. Now many CRT functions that used to work with ints now work with size_ts. This stupid change by MS is sure to break a lot of code when it is ported to Win64.


        You may be right I may be crazy -- Billy Joel -- Within you lies the power for good - Use it!

        1 Reply Last reply
        0
        • A Alois Kraus

          I did some refactoring of some older code and came across this snippet: std::string str("This is a test str"); for(int i=str.length()-1;i>=0;i--) { printf("Examining char %d",i); } The compiler complained about this with a warning: warning C4267: 'initializing' : conversion from 'size_t' to 'int', possible loss of data Being a fan of zero compiler warnings I did give him what he wanted and changed the type of i from int to size_t. Ok it compiles now without any warnings but this change broke many applications during runtime. I was the bad guy of the week because this change was made in a low level library.

          N Offline
          N Offline
          Nemanja Trifunovic
          wrote on last edited by
          #4

          This is one of the reasons I prefer to use a reverse iterator in these "reverse" loops.


          Programming Blog utf8-cpp

          1 Reply Last reply
          0
          • R Rob Graham

            NEVER refactor without unit tests...

            A Offline
            A Offline
            Alois Kraus
            wrote on last edited by
            #5

            I agree. But I must also add: NEVER refactor when not ALL Unit Tests are green. Failing to do so will get you into the bad habit that some test are ok to fail and you miss the new important failed test case.

            1 Reply Last reply
            0
            • A Alois Kraus

              I did some refactoring of some older code and came across this snippet: std::string str("This is a test str"); for(int i=str.length()-1;i>=0;i--) { printf("Examining char %d",i); } The compiler complained about this with a warning: warning C4267: 'initializing' : conversion from 'size_t' to 'int', possible loss of data Being a fan of zero compiler warnings I did give him what he wanted and changed the type of i from int to size_t. Ok it compiles now without any warnings but this change broke many applications during runtime. I was the bad guy of the week because this change was made in a low level library.

              M Offline
              M Offline
              Michael Dunn
              wrote on last edited by
              #6

              I would've expected a compiler warning there about testing an unsigned variable to be >= 0.

              --Mike-- Visual C++ MVP :cool: LINKS~! Ericahist | PimpFish | CP SearchBar v3.0 | C++ Forum FAQ

              I 1 Reply Last reply
              0
              • A Alois Kraus

                I did some refactoring of some older code and came across this snippet: std::string str("This is a test str"); for(int i=str.length()-1;i>=0;i--) { printf("Examining char %d",i); } The compiler complained about this with a warning: warning C4267: 'initializing' : conversion from 'size_t' to 'int', possible loss of data Being a fan of zero compiler warnings I did give him what he wanted and changed the type of i from int to size_t. Ok it compiles now without any warnings but this change broke many applications during runtime. I was the bad guy of the week because this change was made in a low level library.

                Z Offline
                Z Offline
                Zac Howland
                wrote on last edited by
                #7

                More importantly, what was the loop actually doing? (I'm assuming you simplified the code for display purposes here). The reason being ... a custom loop may not have been needed at all.

                If you decide to become a software engineer, you are signing up to have a 1/2" piece of silicon tell you exactly how stupid you really are for 8 hours a day, 5 days a week Zac

                A 1 Reply Last reply
                0
                • Z Zac Howland

                  More importantly, what was the loop actually doing? (I'm assuming you simplified the code for display purposes here). The reason being ... a custom loop may not have been needed at all.

                  If you decide to become a software engineer, you are signing up to have a 1/2" piece of silicon tell you exactly how stupid you really are for 8 hours a day, 5 days a week Zac

                  A Offline
                  A Offline
                  Alois Kraus
                  wrote on last edited by
                  #8

                  You are right that the code posted here was simplified. I have posted it to demonstrate this specific problem. The loop was needed but this variable hoisting optimization did ruin my day. Yours, Alois Kraus

                  1 Reply Last reply
                  0
                  • M Michael Dunn

                    I would've expected a compiler warning there about testing an unsigned variable to be >= 0.

                    --Mike-- Visual C++ MVP :cool: LINKS~! Ericahist | PimpFish | CP SearchBar v3.0 | C++ Forum FAQ

                    I Offline
                    I Offline
                    ITGFanatic
                    wrote on last edited by
                    #9

                    That's the reason the change from int to size_t broke the code, right? By testing for when an unsigned variable becomes negative, it becomes stuck in an infinite loop. I don't see any other plausible reason for such a simple change to break code. Besides that, you shouldn't have to do reverse iteration. Wouldn't the compiler figure out that it's more efficient to iterate in reverse, and automagically add the appropriate code? I'm recalling a quote by some Knuth guy :) about premature optimization and the root of all evil... I mean, if they're going to the trouble to reverse iterate, why not cache string.length() into an int? One might think that repeatedly calling string.length() is going to be detrimental to performance...

                    P 1 Reply Last reply
                    0
                    • A Alois Kraus

                      I did some refactoring of some older code and came across this snippet: std::string str("This is a test str"); for(int i=str.length()-1;i>=0;i--) { printf("Examining char %d",i); } The compiler complained about this with a warning: warning C4267: 'initializing' : conversion from 'size_t' to 'int', possible loss of data Being a fan of zero compiler warnings I did give him what he wanted and changed the type of i from int to size_t. Ok it compiles now without any warnings but this change broke many applications during runtime. I was the bad guy of the week because this change was made in a low level library.

                      W Offline
                      W Offline
                      willbin
                      wrote on last edited by
                      #10

                      str.length() returns an unsigned int.(in MSCRT) so, it's unreliable when you do subtration on it. you should do like below: for (size_t i = 0; i < str.length(); i ++) { printf("Examining char %d",str.length() -i); }

                      //////////////////////////////

                      G

                      P 1 Reply Last reply
                      0
                      • W willbin

                        str.length() returns an unsigned int.(in MSCRT) so, it's unreliable when you do subtration on it. you should do like below: for (size_t i = 0; i < str.length(); i ++) { printf("Examining char %d",str.length() -i); }

                        //////////////////////////////

                        G

                        P Offline
                        P Offline
                        PIEBALDconsult
                        wrote on last edited by
                        #11

                        willbin wrote:

                        for (size_t i = 0; i < str.length(); i ++) { printf("Examining char %d",str.length() -i); }

                        That's another version that should cache the length... it uses the (unchanging) value _twice_ per iteration.

                        1 Reply Last reply
                        0
                        • I ITGFanatic

                          That's the reason the change from int to size_t broke the code, right? By testing for when an unsigned variable becomes negative, it becomes stuck in an infinite loop. I don't see any other plausible reason for such a simple change to break code. Besides that, you shouldn't have to do reverse iteration. Wouldn't the compiler figure out that it's more efficient to iterate in reverse, and automagically add the appropriate code? I'm recalling a quote by some Knuth guy :) about premature optimization and the root of all evil... I mean, if they're going to the trouble to reverse iterate, why not cache string.length() into an int? One might think that repeatedly calling string.length() is going to be detrimental to performance...

                          P Offline
                          P Offline
                          PIEBALDconsult
                          wrote on last edited by
                          #12

                          ITGFanatic wrote:

                          By testing for when an unsigned variable becomes negative, it becomes stuck in an infinite loop. I don't see any other plausible reason for such a simple change to break code.

                          Accessing memory beyond that which was allocated for the string.

                          1 Reply Last reply
                          0
                          Reply
                          • Reply as topic
                          Log in to reply
                          • Oldest to Newest
                          • Newest to Oldest
                          • Most Votes


                          • Login

                          • Don't have an account? Register

                          • Login or register to search.
                          • First post
                            Last post
                          0
                          • Categories
                          • Recent
                          • Tags
                          • Popular
                          • World
                          • Users
                          • Groups