What about that new fangled plus plus thingie?



  • @morbiuswilters said:

    A better reason is: why are you telling the computer to do one thing and then relying on the compiler to fix your mistake?
    I think a better question is: Why did K&R define postincrement as copy-increment-execute-set instead of execute-increment? Also, why do the people who invent new languages tend to copy C, warts and all?



  • @Jaime said:

    @morbiuswilters said:

    A better reason is: why are you telling the computer to do one thing and then relying on the compiler to fix your mistake?
    I think a better question is: Why did K&R define postincrement as copy-increment-execute-set instead of execute-increment? Also, why do the people who invent new languages tend to copy C, warts and all?

    How, exactly, would that work?

    MyClass x = new MyClass();

    MyClass o = x++; // Execute this line before the increment? Who cares?

    o.Something();



  • @Sutherlands said:

    @Jaime said:

    @morbiuswilters said:

    A better reason is: why are you telling the computer to do one thing and then relying on the compiler to fix your mistake?
    I think a better question is: Why did K&R define postincrement as copy-increment-execute-set instead of execute-increment? Also, why do the people who invent new languages tend to copy C, warts and all?

    How, exactly, would that work?

    MyClass x = new MyClass();

    MyClass o = x++; // Execute this line before the increment? Who cares?

    o.Something();

    It would be:

    MyClass x = new MyClass();
    MyClass o = x;
    // Increment x
    o.Something()

    Instead of

    MyClass x = new MyClass();
    MyClass t = new MyClass(x);
    // Increment t
    MyClass o = x;
    x = t;
    o.Something();

    I don't think C# works this way, but some languages do.



  • I'm curious about it, because @Jaime said:

    MyClass x = new MyClass();
    MyClass o = x;
    // Increment x
    o.Something()
    means that the o.Something is still operating on the incremented value.  The only way it would work is if it were a value type, in which case it's already doing the creating of a temporary value.


  • @mallard said:

    @MiffTheFox said:
    @Jaime said:
    From here
    @Douglas Crockford said:
    The ++ (increment) and -- (decrement) operators have been known to contribute to bad code by encouraging excessive trickiness. They are second only to faulty architecture in enabling to viruses and other security menaces. Also, preincrement/postincrement confusion can produce off-by-one errors that are extremely difficult to diagnose.

    God forbid a user find a way to inject code into something that runs... on their own system...

    Unless he's one of those people who don't validate input coming from client-side JavaScript or user Node.js.

    Never heard of an XSS attack then?

    If you can inject JS onto a page and can get someone else to visit such an injected page, you've just injected code onto _their_ computer. Such code could steal cookies, perform website actions with their account, etc... Remember the days of MySpace worms?

    Yeah, but since browsers seem to have gotten the same-origin policy right, an XSS attack would almost always be against the server-side code. The only scenario I can think of that would cause XSS without any chance for server-side validation would be a parameter passed in the URL being displayed on the page as HTML, but that's not due to ++ and --, that's due to a lasy developer using innerHTML (or worse, document.write) instead of createTextNode (or the equivalent methods in whatever JS framework).



  • @boomzilla said:

    The semantics of post-increment say increment the variable but return the value as it was before incrementing. There's really no requirement for a temporary variable. It depends on how the value is being used. In a loop, it's generally discarded. It's no different than being its own statement anywhere else. I wonder if most compilers would create a temporary variable even with optimizations turned off.

    You are correct about the semantics. However, depending on the compiler, arch and usage of the postincrement, it's entirely possible the compiler will have to create a temporary variable. Relying on a compiler optimizing out postincrements also makes code less reliably portable (if the target arch doesn't support the addressing mode, for example). Basically: it's best to avoid postincrements/decrements in C.

    For higher-level languages it's less relevant but still worth asking: if you aren't capturing the value of the postincremented variable, why aren't you using preincrement?


  • ♿ (Parody)

    @morbiuswilters said:

    However, depending on the compiler, arch and usage of the postincrement, it's entirely possible the compiler will have to create a temporary variable. Relying on a compiler optimizing out postincrements also makes code less reliably portable (if the target arch doesn't support the addressing mode, for example). Basically: it's best to avoid postincrements/decrements in C.

    Hmm....I'm having a hard time with this (though I don't have much low level experience outside of x86/64) for C. C++ and operator overloading opens up a new world of WTFs, but for C, you're basically dealing with pointers and numbers, so you don't have the problem of side effects. Again, I'm talking about something like a for loop, where you're not keeping the r-value. Though I'm sure there are still some compilers not bright enough to notice what's going on there.

    All that said, I use preincrements pretty much all of the time. If I come across a case where I really need postincrement, I would most likely break it up into multiple statements for clarity's sake. Like most things, it's rarely a performance issue.



  • @MiffTheFox said:

    Yeah, but since browsers seem to have gotten the same-origin policy right, an XSS attack would almost always be against the server-side code.

    How does SOP protect against XSS?

    @MiffTheFox said:

    The only scenario I can think of that would cause XSS without any chance for server-side validation would be a parameter passed in the URL being displayed on the page as HTML, but that's not due to ++ and --, that's due to a lasy developer using innerHTML (or worse, document.write) instead of createTextNode (or the equivalent methods in whatever JS framework).

    That's how a lot of XSS happens. Not saying it's not incompetence, but still. And of course, this has nothing to do with ++.



  • @boomzilla said:

    Hmm....I'm having a hard time with this (though I don't have much low level experience outside of x86/64) for C. C++ and operator overloading opens up a new world of WTFs, but for C, you're basically dealing with pointers and numbers, so you don't have the problem of side effects. Again, I'm talking about something like a for loop, where you're not keeping the r-value. Though I'm sure there are still some compilers not bright enough to notice what's going on there.

    You're basically correct that the compiler is just going to do the right thing in a simple for loop. My point is that it's really just a bad habit to use a postincrement where a preincrement is sufficient.

    @boomzilla said:

    All that said, I use preincrements pretty much all of the time. If I come across a case where I really need postincrement, I would most likely break it up into multiple statements for clarity's sake. Like most things, it's rarely a performance issue.

    I agree. And I generally think using postincrements at all is a bad habit; like you I would break it into separate assignment and preincrement steps to make things clearer.


  • ♿ (Parody)

    @morbiuswilters said:

    @MiffTheFox said:
    The only scenario I can think of that would cause XSS without any chance for server-side validation would be a parameter passed in the URL being displayed on the page as HTML, but that's not due to ++ and --, that's due to a lasy developer using innerHTML (or worse, document.write) instead of createTextNode (or the equivalent methods in whatever JS framework).

    That's how a lot of XSS happens. Not saying it's not incompetence, but still. And of course, this has nothing to do with ++.

    It's the broken window theory of developer sloth! First, you're preincrementing. Then you stop sanitizing input. Pretty soon, you're building dynamic SQL with string concatenation, and eventually you just copy and paste random code from the web until it renders in under a minute.



  • @boomzilla said:

    @morbiuswilters said:
    @MiffTheFox said:
    The only scenario I can think of that would cause XSS without any chance for server-side validation would be a parameter passed in the URL being displayed on the page as HTML, but that's not due to ++ and --, that's due to a lasy developer using innerHTML (or worse, document.write) instead of createTextNode (or the equivalent methods in whatever JS framework).

    That's how a lot of XSS happens. Not saying it's not incompetence, but still. And of course, this has nothing to do with ++.

    It's the broken window theory of developer sloth! First, you're preincrementing. Then you stop sanitizing input. Pretty soon, you're building dynamic SQL with string concatenation, and eventually you just copy and paste random code from the web until it renders in under a minute.

    I prefer Morbius' Grand Unified Theory of Language Evangelist Derangement: you start out by boldly telling people that a much-reviled language is actually misunderstood; you gain notoriety as you demonstrate how said language is a powerful tool; then you end up on the board for the next version of the spec; you start ranting at people who rely on automatic semicolon insertion; then you preach against the evils of increment operators; finally you find yourself in a dark alley, having a train run on you by Bjarne Stroustrup and James Gosling, and it's at that moment that C++0x finally makes sense.



  • @morbiuswilters said:

    it's at that moment that C++0x finally makes sense.
     

    True. I'm not there yet.



  • @Sutherlands said:

    @powerlord said:

    The real wtf is using .Length instead of GetLength(0), right?

    No.  We don't even know if this is an array, much less a multi-dimensional array.  It probably doesn't have that method.

    .NET has a collection type with a .Length property?  I'm pretty sure they all use .Count.  That's what ArrayList,  List<T>, and Dictionary<T> all use at any rate.

    Besides, as pointed out by the OP, MyCollection being an Array rather than a Collection is one of the WTFs:

    @rstinejr said:

    BTW -- the instance variable MyCollection might make you wonder about our naming conventions. As far as I can tell, the corporate standard for instance variables is random choice for initial cap vs. initial lower case. And the "Collection" is really an array. Harumph!

    The problem with .NET's Array.Length is that its use in for (and whether foreach is safe on it) is entirely dependent on the Array type.  They're safe on 1D and Jagged arrays, but won't do what you expect on multi-dimensional arrays.  Inconsistency is a major problem in programming languages... I seem to recall another user posting a huge PHP rant just recently about it.



  • @pkmnfrk said:

    @boomzilla said:
    @dhromed said:
    @boomzilla said:
    If you were asked about the length of a rectangular prism, would you compute the area of a face, or just go right to the volume?
    A multidimensional array is a set of discrete points, not a volume.

    Yes, but I've never seen a set's measurement described as "length." If the method in question were "size," then it would make sense. Length is a measurement of a single dimension. A multidimensional array is, by definition, not of a single dimension.

    I think everyone is looking at this the wrong way. Considering that arrays don't also have Width and Height properties, I think it's safe to assume that Length is not referring to a spatial dimension. Length is the size of the array, such that the memory footprint of the array is Length * sizeof(T) + object overhead (If T is a reference type, then sizeof(T) is the size of a pointer, but that's beside the point).

    Consider if Length was actually the size of dimension 0. Well, now there's two ways to get the size of dimension 0, which is a violation of DRY. Further, dimensions 1+ only have one way to retrieve them, which is weird. Also, what if you want to know the total number of elements? Well, the computer knows, but it isn't telling you, so you need to calculate it manually: GetUpperBound(0) * GetUpperBound(1) * GetUpperBound(2) * ...

    Finally, the documentation explicitly spells it out for you, so there shouldn't be any reason for confusion in the first place:

    @MSDN said:

    Length Gets a 32-bit integer that represents the total number of elements in all the dimensions of the Array.

    @boomzilla said:

    @dhromed said:
    What is the length of 8-bit RGB colour space?

    I'm not sure "length" makes sense here. I suppose the implementation could be a total of 8-bits, so you could consider it an array of 8 bits, or a single byte. Or maybe it's an array of three color values. It would depend upon the implementation.

    The length of 8-bit colour space is the number of unique colours that can be represented in 8-bits. Doesn't matter if you use something like RRGGGBBB or if you go for an indexed palette scheme, the number of unique colours is still only 256. Thus, RGBColourSpace.Length == 256.

     

    And as I was trying to point out, too subtley apparently, is that .Length is totally useless as it currently is in the framework.  Seriously, the only reason it exists is because Java arrays have a .length, and the .NET arrays and collections are basically improved (most of the time) copies of their Java versions.  The problem with this is that C# has real multidimensional support while Java didn't, so .length is Java really is just the length.  When C# was written, they decided that .Length should be the entire array's dimensions instead for multidimensional arrays.  However, as previously pointed out, [url=http://msdn.microsoft.com/en-us/library/2s05feca.aspx]Jagged arrays[/url] work just like Java arrays do.

     



  • @powerlord said:

    The problem with .NET's Array.Length is that its use
    in for (and whether foreach is safe on it) is entirely dependent on the
    Array type.  They're safe on 1D and Jagged arrays, but won't do what you expect on
    multi-dimensional arrays.  Inconsistency is a major problem in
    programming languages... I seem to recall another user posting a huge
    PHP rant just recently about it.

    You know, I don't know what an enumerator for a 2d array would do. I suspect that it would go in memory order (I forget if .NET is row-major or column-major), but I have nothing to base that off of. A jagged array, however, is completely different, being an array of other arrays. In that case, the enumerator will return each sub array in order. You would need a nested foreach loop to get all the individual values.



  • @powerlord said:

    And as I was trying to point out, too subtley apparently, is that .Length is totally useless as it currently is in the framework.  Seriously, the only reason it exists is because Java arrays have a .length, and the .NET arrays and collections are basically improved (most of the time) copies of their Java versions.  The problem with this is that C# has real multidimensional support while Java didn't, so .length is Java really is just the length.  When C# was written, they decided that .Length should be the entire array's dimensions instead for multidimensional arrays.  However, as previously pointed out, Jagged arrays work just like Java arrays do.

     

    Are you saying that it's never useful to know the total number of elements in an array? Why would that be the case? Maybe you don't know or care the dimensions of the 2D array, but you do care about the total number of elements. I can't think of anything off the top of my head, but the possibility exists.



  • @pkmnfrk said:

    I don't know what an enumerator for a 2d array would do. I suspect that it would go in memory order (I forget if .NET is row-major or column-major), but I have nothing to base that off of

    Read the second example



  • The heck with ++   use - -  like this

        i = (i - -1)



  • @TheCPUWizard said:

    The heck with ++   use - -  like this

        i = (i - -1)

    That's not even valid C. Is there any language where that works?



  • @morbiuswilters said:

    @TheCPUWizard said:

    The heck with ++   use - -  like this

        i = (i - -1)

    That's not even valid C. Is there any language where that works?

    Why wouldn't it be valid C? It's just subtracting a negative number. Works fine in ECMAScript.

    I prefer the look of this though:

    i-=-1

     

     



  • @morbiuswilters said:

    That's not even valid C.
    gcc thinks otherwise:
    $ cat test.c && gcc test.c -o test && ./test
    #include <stdio.h>
    int main()
    {
    int i=1;
    i = (i - -1);
    printf(">> %d\n",i);
    }

    2



  • @ender said:

    @morbiuswilters said:
    That's not even valid C.
    gcc thinks otherwise:
    $ cat test.c && gcc test.c -o test && ./test
    #include <stdio.h>
    int main()
    {
    int i=1;
    i = (i - -1);
    printf(">> %d\n",i);
    }

    >> 2

    Ah, on my screen the spaces aren't at all obvious so it looks like: i<postdecrement>1



  • @morbiuswilters said:

    @ender said:
    @morbiuswilters said:
    That's not even valid C.
    gcc thinks otherwise:
    $ cat test.c && gcc test.c -o test && ./test
    #include <stdio.h>
    int main()
    {
    int i=1;
    i = (i - -1);
    printf(">> %d\n",i);
    }

    >> 2

    Ah, on my screen the spaces aren't at all obvious so it looks like: i<postdecrement>1

    Have you heard about the Goes Toward operator? It looks like an arrow, so it's very memorable!

    int i = 10;
    while(i --> 0) { //pronounced "while i goes toward 0"
       printf(%d\n", i); //prints 9, 8, 7, 6, etc
    }


  • @pkmnfrk said:

    Have you heard about the Goes Toward operator? It looks like an arrow, so it's very memorable!

    int i = 10;
    while(i --> 0) { //pronounced "while i goes toward 0"
       printf(%d\n", i); //prints 9, 8, 7, 6, etc
    }
    We now have an example of "excessive trickiness".


  • @pkmnfrk said:

    @morbiuswilters said:
    @ender said:
    @morbiuswilters said:
    That's not even valid C.
    gcc thinks otherwise:
    $ cat test.c && gcc test.c -o test && ./test
    #include <stdio.h>
    int main()
    {
    int i=1;
    i = (i - -1);
    printf(">> %d\n",i);
    }

    >> 2

    Ah, on my screen the spaces aren't at all obvious so it looks like: i<postdecrement>1

    Have you heard about the Goes Toward operator? It looks like an arrow, so it's very memorable!

    int i = 10;
    while(i --> 0) { //pronounced "while i goes toward 0"
       printf(%d\n", i); //prints 9, 8, 7, 6, etc
    }

    Look out, i, White Pac-Man is only two dots away from eating you!!



  • @Jaime said:

    foreach uses the enumerator on the class it's enumerating. I've yet to run across an enumerator that's non-deterministic.
     

    Aha!  Thanks for giving me a new goal in my next coding assignment...



  • Actually there are quite a few that are "non-deterministic" depending on exactly how you mean that. Some of the newer iterators and enumerators (they are different things) will allow the underlying collections to be modified. Other will look at the current state of the objects to determine which on is next to return. So, assume you are iterating over a collection that is actively sorted by "FOO" so that MoveNext will position at the element that has the next highest FOO at the time of the call to MoveNext. Now assume that FOO really dynamic (ie changes over time). Depending on exactly when you iterate the collection, you will get the items in a different order each time. If the MoveNext logic has filtering, you will get different elements...

    This is not theoretical...the most common case I have seen is in "priority" based schedulers / queues...



  • @TheCPUWizard said:

    Some of the newer iterators and enumerators (they are different things) will allow the underlying collections to be modified

    Then, they are implementing them wrong (at least in c#)
    @TheCPUWizard said:
    Depending on exactly when you iterate the collection, you will get the items in a different order each time.

    If FOO is part of the object then the object has changed so you are not iterating the same collection (also is a violation of the specs)
    @TheCPUWizard said:
    This is not theoretical...the most common case I have seen is in "priority" based schedulers / queues...

    If they are doing it in c# you should consider letting them know that they are violating the specs (and for that they should die in a fire).



  • @serguey123 said:

    ....they are violating the specs

    I disagree. Of course you could prove me wrong by providing the specification (or reference to same).



  • @serguey123 said:

    ....they are violating the specs

    I disagree. Of course you could prove me wrong by providing the specification (or reference to same).



  • @TheCPUWizard said:

    @serguey123 said:

    ....they are violating the specs

    I disagree. Of course you could prove me wrong by providing the specification (or reference to same).

    "The foreach statement is used to iterate through the collection to get the information that you want, but can not be used to add or remove items from the source collection to avoid unpredictable side effects."

    http://msdn.microsoft.com/en-us/library/ttw7t8t6(v=vs.100).aspx

    "Enumerators can be used to read the data in the collection, but they cannot be used to modify the underlying collection."

    http://msdn.microsoft.com/en-us/library/78dfe2yb.aspx



  • @serguey123 said:

    @TheCPUWizard said:

    @serguey123 said:

    ....they are violating the specs

    I disagree. Of course you could prove me wrong by providing the specification (or reference to same).

    "The foreach statement is used to iterate through the collection to get the information that you want, but can not be used to add or remove items from the source collection to avoid unpredictable side effects."

    http://msdn.microsoft.com/en-us/library/ttw7t8t6(v=vs.100).aspx

    "Enumerators can be used to read the data in the collection, but they cannot be used to modify the underlying collection."

    http://msdn.microsoft.com/en-us/library/78dfe2yb.aspx

    Neither of those apply to what I posted.  "foreach" is not necessarily involved - it is the implementation of MoveNext and Current that I am referring to. Additionally the information is readonly and the collection is not modified.

    There are no specifications about which specific element in a collection MoveNext must position as the current element, nor is there any specification that every element in the collection be returned. The simple example is enumerators returned by LINQ expressions that have "where" and "orderby" clauses. The same collection with the same contents being used as the readonly datasource, with the resulting items being controlled by the parameters. The primary difference, is that in the cases I am referring to the parameters are allowed to impact an inprogress enumeration (i.e. the enumerator is not at the reset state).

    But once again, there is nothing in the specifications you provided (nor am I aware of any in existance) which address this issue.



  • @TheCPUWizard said:

    Neither of those apply to what I posted

    You said: "Some of the newer iterators and enumerators (they are different things) will allow the underlying collections to be modified". According to the docs this is wrong to do. The foreach construct is for simple iteration, just read the docs, ok? I'll post more on wenesday.



  • @serguey123 said:

    @TheCPUWizard said:
    Neither of those apply to what I posted
    You said: "Some of the newer iterators and enumerators (they are different things) will allow the underlying collections to be modified". According to the docs this is wrong to do. The foreach construct is for simple iteration, just read the docs, ok? I'll post more on wenesday.

    You are correct, I did post that, and I was WRONG in what I posted. My apologies to you and to the community. My intended point (which I screwed up royally) was about the "simple" part..as I (hopefully) showed in my more recent post.



  • @TheCPUWizard said:

    You are correct, I did post that, and I was WRONG in what I posted. My apologies to you and to the community. My intended point (which I screwed up royally) was about the "simple" part..as I (hopefully) showed in my more recent post.

    Are you allowed to admit you're wrong on a forum?  I thought that was against the internet rules.



  • @Peraninth said:

    @TheCPUWizard said:

    You are correct, I did post that, and I was WRONG in what I posted. My apologies to you and to the community. My intended point (which I screwed up royally) was about the "simple" part..as I (hopefully) showed in my more recent post.

    Are you allowed to admit you're wrong on a forum?  I thought that was against the internet rules.

    Yes, many people are suprised that this is allowed. Some will even deny it. Ironically I often make the claim that I have made more mistakes than nearly any other developer I have encountered. This should not be suprising since even small rates accumulate great volume over time (I passed the 1.2M hours mark just under a year ago...), so there are a number of places you can find where I have made such admissions in the past.



  • Consecutive Errors...I need to get some sleep... [should have been 120K, not 1.2M]



  • @TheCPUWizard said:

    You are correct, I did post that, and I was WRONG in what I posted. My apologies to you and to the community

    I'm framing this and hanging it on a wall ;)


Log in to reply