|
That's right. It was somewhat conversational with a hint of arrogant superiority. You wrote "this" (you bonehead). PL/C chooses to do "this". If smileys had been invented then I'm sure it would have followed with a :P
|
|
|
|
|
In c++, VS 2005, the unoptimized code is actually kind of stupid
i = i++;
mov eax,dword ptr [i (40904Ch)]
mov dword ptr [i (40904Ch)],eax
mov ecx,dword ptr [i (40904Ch)]
add ecx,1
mov dword ptr [i (40904Ch)],ecx
It gets i, stores it in i, gets i, increments i, stores it in i. Not sure why it thinks it needs to do the first 2 steps.
When I turn on "optimized for speed" (not comfort like me) it generates the exact same (smart) code as
++i;
|
|
|
|
|
the stoopit code is pretty normal since i=i++; falls apart in i=i; and i++; and that is what the assembly code does, without any optimization.
Luc Pattyn [Forum Guidelines] [My Articles]
- before you ask a question here, search CodeProject, then Google
- the quality and detail of your question reflects on the effectiveness of the help you are likely to get
- use the code block button (PRE tags) to preserve formatting when showing multi-line code snippets
|
|
|
|
|
When I turn on "optimized for speed" (not comfort like me) it generates the exact same (smart) code as
++i;
Wouldn't a more efficient implementation be to simply do nothing, given the lack of a sequence point between the increment and the assignment? Not that I'd generally expect a compiler to find that optimization, but I would have expected code like:
mov eax,[_i] ; Fetch value before increment
inc dword [_i] ; Do increment
mov [_i],eax ; Store fetched value
which would, of course, effectively do nothing.
BTW, is there any guarantee about the behavior of "do_something(var++)" if do_something references var? What about "i=++i"? Even though it's hard to imagine that "i=++i;" would do anything other than increment "i", I don't think there's any guarantee that it won't?
|
|
|
|
|
supercat9 wrote: Wouldn't a more efficient implementation be to simply do nothing, given the lack of a sequence point between the increment and the assignment? Not that I'd generally expect a compiler to find that optimization, but I would have expected code like: mov eax,[_i] ; Fetch value before increment inc dword [_i] ; Do increment mov [_i],eax ; Store fetched valuewhich would, of course, effectively do nothing.
BTW, is there any guarantee about the behavior of "do_something(var++)" if do_something references var? What about "i=++i"? Even though it's hard to imagine that "i=++i;" would do anything other than increment "i", I don't think there's any guarantee that it won't?
This code doesn't "do nothing"
i = i++;
It still has to inc i and store it in i. It is just a long form of
++i;
The VS optimizer usually does a pretty good job. I had to heavily optimize some code a few years ago. I don't remember which VS version I was using, but I was impressed with the code it came up with.
In this case it generates
mov eax,1
add dword ptr [i],eax
This seems a little strange to me. Maybe an "add" is much faster than an "inc". It's been a while since I was optimizing asm code.
do_something(var++) is going to push the current var on the stack, call do_something, then inc var. Nothing strange about that.
|
|
|
|
|
CurtD wrote: do_something(var++) is going to push the current var on the stack, call do_something, then inc var. Nothing strange about that.
Really? The compiler I tested performed the increment before the function call.
|
|
|
|
|
From MSDN
When a postfix operator is applied to a function argument, the value of the argument is not guaranteed to be incremented or decremented before it is passed to the function. See section 1.9.17 in the C++ standard for more information.
So, like so much in life, you just roll the dice and take your chances.
|
|
|
|
|
CurtD wrote: This code doesn't "do nothing"
If the variable i is equal to five before the statement, "i = i++;" is executed, would it not be legitimate for the compiler's generated code to read i (five), increment i (yielding and storing six), and then store the read value back to i (setting it back to 5)? If the variable i is not volatile, would not a legitimate optimization thus be to eliminate the statement altogether?
Out of curiosity, I wonder if there are any compilers which do not always update a variable used with a pre-increment before making use of the pre-incremented value? It's possible to contrive examples where the optimal code would in fact use (var+1) in the expression and then later store the incremented value to the variable, but I doubt compilers would find such optimizations.
|
|
|
|
|
supercat9 wrote: If the variable i is equal to five before the statement, "i = i++;" is executed, would it not be legitimate for the compiler's generated code to read i (five), increment i (yielding and storing six), and then store the read value back to i (setting it back to 5)? If the variable i is not volatile, would not a legitimate optimization thus be to eliminate the statement altogether?
Well, according to MSDN, the C++ standard does not define the proper behavior when a postfix is applied to a function arg. If anyone knows why they decided to leave it up to the compiler writers instead of deciding on a "standard", I would love to know the reason. The best thing to do is not write code like this.
MSDN doesn't say specifically how a postfix is supposed to behave in the example i = i++. But, VS 2005 inc's i before storing it in i -- I assume because of operator precedence.
supercat9 wrote: Out of curiosity, I wonder if there are any compilers which do not always update a variable used with a pre-increment before making use of the pre-incremented value? It's possible to contrive examples where the optimal code would in fact use (var+1) in the expression and then later store the incremented value to the variable, but I doubt compilers would find such optimizations.
When playing with this example, the optimizer did just that in one case -- it kept (i+1) in a reg, used it a few times, and stored it later.
The VS compiler will optimize away code that doesn't do anything.
void donothing()
{
int i = 5;
i++;
}
No code is generated for donothing() and any call to it is ignored.
|
|
|
|
|
For more fun from the C++ standard:
[ Example:
i = v[i++]; // the behavior is undefined
i = 7, i++, i++; // i becomes 9
i = ++i + 1; // the behavior is undefined
i = i + 1; // the value of i is incremented
—end example ]
I think the best programming practice is to avoid "undefined" behavior.
modified on Tuesday, March 24, 2009 2:43 PM
|
|
|
|
|
catch (Exception ex)
{
//we should probably report errors
}
|
|
|
|
|
at least they left you a message to let you know what should happen... I've seen them not even try and catch an exception.
|
|
|
|
|
catching and doing nothing is actually worse. It completely hides the fact that anything went wrong. Which uually means you crash somewhere else later.
|
|
|
|
|
Well there are lots of cases where catching and doing nothing is ok.
|
|
|
|
|
Add TODO: to the comment, so Visual Studio can remind you something still needs to be improved.
Luc Pattyn [Forum Guidelines] [My Articles]
- before you ask a question here, search CodeProject, then Google
- the quality and detail of your question reflects on the effectiveness of the help you are likely to get
- use the code block button (PRE tags) to preserve formatting when showing multi-line code snippets
|
|
|
|
|
Reminds me of Resume Next from a particularly dark past!
Never underestimate the power of human stupidity
RAH
|
|
|
|
|
Reminds me of Resume Next from a particularly dark past!
Somewhat, but it's easier to limit the effect of catch-and-ignore to a single statement. Realistically, there are quite a few circumstances in which if an error happens very often the developer should be made aware of it, but beyond that there's no particularly useful action the code can take in response to an error.
For example, if a field that affects the display of a control is changed outside the UI thread, it's necessary to use BeginInvoke to let the control update itself. If the BeginInvoke works, great. If it fails because someone closed a window at just the "right" time, so what? It's important to ensure that the code doesn't waste time repeatedly trying to BeginInvoke a control after it's disposed, but otherwise occasional invocation failures should be expected and I really don't see anything useful to be done with them other than ignore them.
|
|
|
|
|
supercat9 wrote: Somewhat, but it's easier to limit the effect of catch-and-ignore to a single statement. Realistically, there are quite a few circumstances in which if an error happens very often the developer should be made aware of it, but beyond that there's no particularly useful action the code can take in response to an error.
In my app, this is the rare case. I think I have one or two and I commented like this
catch(Exception e)
{
// nothing we can do about an error here
}
Unfortunately, for a lot of people, exception handling consists of
catch(...)
{
}
Somewhere they learned this is the proper way to handle exceptions. If it prevents the app from crashing (at this point anyway), that's all you need to do. If you blow up a buffer, hide it and let the next guy deal with it.
|
|
|
|
|
If something like an empty try/catch is discovered in code that I am in charge of (and believe me, I will discover it, thanks to FxCop), I will refuse to accept it for production code.
If an error happens and absolutely no action can or should be taken (a very rare case), then at least the exception has to be logged and there has to be a comment in the code that explains why it's OK to just "swallow" the exception in this special case. This is the very least for good code...
Regards
Thomas
www.thomas-weller.de
Programming today is a race between software engineers striving to build bigger and better idiot-proof programs, and the Universe trying to produce bigger and better idiots. So far, the Universe is winning. Programmer - an organism that turns coffee into software.
|
|
|
|
|
Thomas Weller wrote: If something like an empty try/catch is discovered in code that I am in charge of (and believe me, I will discover it, thanks to FxCop), I will refuse to accept it for production code.
If an error happens and absolutely no action can or should be taken (a very rare case), then at least the exception has to be logged and there has to be a comment in the code that explains why it's OK to just "swallow" the exception in this special case. This is the very least for good code...
Regards
Thomas
All I can add is AMEN
I will confess that in my code above where I "swallowed" the exception was when a thread was ending and his parent had already disappeared. Which in practice, has never happened. I believe that is the only time I have done this.
I sent out an email a few years ago telling people to add exception handling (since I throw exceptions) and their response was to add catch (...) {} all over the place. Fortunatley, I log all exceptions at the source.
|
|
|
|
|
I agree.
There are some rare cases where doing nothing is the correct thing to do. A third-party library we use throws an exception if you call Init() more than once, but doesn't actually mess up the state of the library. Our app is multithreaded, so we have an empty catch block there.
Mind you, these edge cases are well documented with comments.
|
|
|
|
|
Yes, sometimes is a good reason to use an empty catch. It still only acceptable if it is well documented as to why it was done so that some poor programmer a few years down the road doesn't have to waste time trying to figure out how the exception should really be handled.
Just because the code works, it doesn't mean that it is good code.
|
|
|
|
|
LMAO
|
|
|
|
|
I saw this at work. I guess the coder wanted to do a series of validations and return an error when the first failure condition was found. I don't know if you'll consider this a horror or not, but it is definitely a backwards way of doing this.
Select Case (true)
Case [failure condition 1]
Throw New Exception("Condition 1 failed.")
Case [failure condition 2]
Throw New Exception("Condition 2 failed.")
'etc...
Else
'Success!
End Select
|
|
|
|
|
Looks ok for me. Why a backwards way?
Greetings - Gajatko
Portable.NET is part of DotGNU, a project to build a complete Free Software replacement for .NET - a system that truly belongs to the developers.
|
|
|
|
|