Post your code optimizations

DiGuru said:
I don't think it has a return value, as it shouldn't be a value. The value during execution would be just i, nothing more. And afterwards, i would be incremented. Twice. That's the idea about it, AFAIK.
Nope. You should look into how these operations are overloaded :) I think Mate's right, though, and it would generate a compile error.
 
Chalnoth said:
Nope. You should look into how these operations are overloaded :) I think Mate's right, though, and it would generate a compile error.
If true, what's the difference between pre and postincrement?
 
Mate Kovacs said:
The post[++/--] operators need and lvalue as argument, and they return a non-lvalue. So expressions like "1++" and "(i++)++" are invalid.
I played with G++ for a moment, and it indeed says "error: non-lvalue in increment" on "i = (i++)++" and "2++" as well as on "++2". It doesn't like "i++ = i" either ("error: non-lvalue in assignment").
But as it turns out, things like "++i = 2", "(++i)++" and "int *p = &--i" are legal :eek:, so the pre[++/--] operators seem to return a reference to the argument.

EDIT: GCC doesn't like the "strange stuff", so I guess it's not valid C code.
 
Last edited by a moderator:
DiGuru said:
If true, what's the difference between pre and postincrement?
Well, the timing of when pre-increment and post-increment are executed isn't defined, so post increment can indeed be evaluated before the rest of the statement is executed (this probably isn't done for built-in types, for performance reasons, but may be for other types).

Here's an example of how these are overloaded:
http://www.cs.bu.edu/teaching/cpp/overload/incr-op.html

Notice that the pre- and post- increment operators are completely different function calls, with the return value set by the function, such that one might expect the following:
x = 1;
x += x++ + x++;
...to result in x = 6. That is, if the evaluation order is left to right, we can incrementally replace the functions by their return values, recording the value of x at each step:
x += x++ + x++; (x = 1)
x += 1 + x++; (x = 2)
x += 1 + 2; (x = 3)
(x = 6)

Instead, if the compiler doesn't evaluate the ++'s until after the statement, for the purpose of performance (which seems likely), then the result would be x = 5.

edit:
Yes, if I use the integer type for the above statement, the resultant value for x is 5. If I make a little integer container class and overload the above operators, the return value is 6.
 
Mate Kovacs said:
But as it turns out, things like "++i = 2", "(++i)++" and "int *p = &--i" are legal :eek:, so the pre[++/--] operators seem to return a reference to the argument.
That makes sense. You can't return a reference with the postfix operators, since the value has already changed, and you don't want to return the changed value.
 
So, postincrement creates a temporary variable. Should we consider that a compiler error? As in: the compiler does it wrong?
 
Mate Kovacs said:
Does anybody here know which tools is he referring to?
Knowing C/C++, the existence of such tools wouldn't be surprising, but frankly I've never heard of any.
you should
have a look at lint by gimpel software (IIRC). I am not sure if it warns you for unfeined behaviour due to undefined evaluation order, but i would suspect that it does. highly recomended.

http://www.gimpel.com/

edit: added link, the "bug of the month" archive on gimpel's site is fun to read too.
 
Last edited by a moderator:
Chalnoth said:
Well, the timing of when pre-increment and post-increment are executed isn't defined, so post increment can indeed be evaluated before the rest of the statement is executed (this probably isn't done for built-in types, for performance reasons, but may be for other types).
If that isn't an error in the compiler, at least it's extremely sloppy and in no way according to the intent of the statement. IMHO.
 
DiGuru said:
If true, what's the difference between pre and postincrement?
Conceptually:
Code:
// preincrement
int& operator++(int& i)
{
  i += 1;
  return i;
}

// postincrement
int operator++(int& i, int dummy_to_make_this_postincrement)
{
  int returnvalue = i;
  i += 1;
  return returnvalue;
}
Note that preincrement returns a reference, postincrement returns a value.
Postincrement cannot return a reference, because it's whole point is to return a different value from the one it has modified.
 
Xmas said:
Postincrement cannot return a reference, because it's whole point is to return a different value from the one it has modified.
Yes, but it should increment the variable *after* the statement is executed. That's the whole idea about it. And no matter if that variable changed in the execution of the statement, or where you put it. Just execute the expression, take the original lvalue and increment the rvalue.
 
Btw, I do understand that they did it like that to make it possible to overload them easily. That's no excuse in my book. Do it right, or don't bother. But I know we have to take it into account, because that's how it is.
 
diGuru:
That's your interpretation, but it's not what the spec says.

This is not about sloppy compilers, they do exactly what the specification intended. That is, the specification intensionally left it up to the compiler to do the actual increment whenever it wants (beteen use and end of statement). In many cases it makes most sense to do the increment directly (you already have the value in a register, and maybe a pointer to the place it should be stored). In some cases it's best to wait until the whole expression is calculated (extremely register limited).

So whenever doing a X++ or ++X, don't touch X in the same expression (and that includes the left hand side of assignements).

Code:
i = 2;
i *= i++;

// Could be:
i = 2;
iTemp = 2;
i++;         // => 2+1 = 3
i *= iTemp;  // => 3*2 = 6

// or:
i = 2;
iTemp = 2;
i *= iTemp;  // => 2*2 = 4
i++;         // => 4+1 = 5
 
DiGuru said:
Btw, I do understand that they did it like that to make it possible to overload them easily. That's no excuse in my book. Do it right, or don't bother. But I know we have to take it into account, because that's how it is.
"Do it right" = the way C# and Java do it IMO. I.e. evaluate from left to right and perform the increment right where it occurs. Not at some arbitraty time afterwards.
 
Basic said:
diGuru:
That's your interpretation, but it's not what the spec says.

This is not about sloppy compilers, they do exactly what the specification intended. That is, the specification intensionally left it up to the compiler to do the actual increment whenever it wants (beteen use and end of statement). In many cases it makes most sense to do the increment directly (you already have the value in a register, and maybe a pointer to the place it should be stored). In some cases it's best to wait until the whole expression is calculated (extremely register limited).
Yes, I get that. But, if you're designing a language, do you try to make it hard (inconsistent) on the developer to perhaps save a few cycles here and there, or do you want to be consistent?

That's why people react so strong to things like this.
 
Xmas said:
"Do it right" = the way C# and Java do it IMO. I.e. evaluate from left to right and perform the increment right where it occurs. Not at some arbitraty time afterwards.
Agreed. Things like that are the main part why I don't like C/C++. If C#/Java would also allow things like non-class declarations, I would be completely happy with them.
 
Xmas said:
"Do it right" = the way C# and Java do it IMO. I.e. evaluate from left to right and perform the increment right where it occurs. Not at some arbitraty time afterwards.
DiGuru said:
But that's the opposite of what you wanted out of C. You wanted C to increment the value at the end of the statement.

I'd say that it's an error prone and bad coding style to use expressions with side effects together with the variables it changes in the same expression. So if there's an error in the syntax, then it's that it allows it at all.
 
Basic said:
But that's the opposite of what you wanted out of C. You wanted C to increment the value at the end of the statement.

I'd say that it's an error prone and bad coding style to use expressions with side effects together with the variables it changes in the same expression. So if there's an error in the syntax, then it's that it allows it at all.
Yes, I agree. That would be best, and C# isn't doing that either. But at least it's consistent. I'll settle for that, given the choice. But both ways are sloppy, IMO. That's why I like Delphi (Object Pascal) best. It always does what I expect it to do, unless I make logic errors, of course.

;)

Edit: it doesn't have operator overloading, templates or all the other stuff that created those inconsitencies in the first place either. Which might just be why I like it. ;)
 
Last edited by a moderator:
gizzz just do one operation per line people ;p
Besides real coders use ++i and not i++ :p :p :p

<ok sorry, but we are off topic for a little while now> ^^
 
DiGuru said:
Edit: it doesn't have operator overloading, templates or all the other stuff that created those inconsitencies in the first place either. Which might just be why I like it. ;)
Operator overloading can be so nice for making readable code, though. It has to be done right, of course, but can be a fantastic help.
 
Chalnoth said:
Operator overloading can be so nice for making readable code, though. It has to be done right, of course, but can be a fantastic help.
Yes. But I rather type a bit more than having to guess about how my code might be executed.
 
Back
Top