|
Hi Nish,
Glad you agree.
btw, thanks for the mass of no-nonsense articles you already wrote.
Keep up the good work!
Geert.
|
|
|
|
|
Are you sure you got you're code right? CompareNoCase returns 0 when the strings are equal, -1 if less then, 1 when greater.
Joel Lucsy (jjlucsy@ameritech.net)
|
|
|
|
|
Looks like he's doing the right thing.
/ravi
"There is always one more bug..."
http://www.ravib.com
ravib@ravib.com
|
|
|
|
|
Ravi's right. I disagree with the coding style, but it is technically correct.
Cheers,
Tom Archer
Author - Inside C#, Visual C++.NET Bible
Warning: The deadline in your mirror is much closer than it appears.
|
|
|
|
|
True. Assuming non-zero is "true" can result in hard-to-find bugs. I'd much rather write:
CFoo* pFoo = new CFoo();
if (pFoo != NULL) {
...
}
than
CFoo* pFoo = new CFoo();
if (pFoo) {
...
}
/ravi
Let's try putting "civil" back into "civilization"
http://www.ravib.com
ravib@ravib.com
|
|
|
|
|
Hi ravi,
It's beyond this article, but could you give an example of code assuming non-zero is TRUE resulting in errors?
Just interested.
Geert.
|
|
|
|
|
Hi Geert,
Quite often, people code functions that return 1 on normal successful completion, and zero on generic error. This code often gets called as:
long nStatus = someFunction();
if (!nStatus) {
reportError();
return;
}
...
As time goes by, someFunction() could be modified to return more specific status values. A developer who's chosen 1 to be success and zero to be error is likely to use status values <0 to represent new error conditions, which would cause the code shown above to break. I've seen this pretty often with less experienced developers.
It would've been safer to write:
#define SOMEFUNC_SUCCESS 1
long nStatus = someFunction();
if (nStatus != SOMEFUNC_SUCCESS) {
reportError();
return;
}
...
/ravi
Let's try putting "civil" back into "civilization"
http://www.ravib.com
ravib@ravib.com
|
|
|
|
|
Sorry , Ravi, but this example , IMHO is unfortunate !
First , a Standard compiler throws up a std::bad_alloc if a object fails to be created on the heap , second , if the compiler by default, is configured to return NULL on the allocation of objects on the heap (VC++ 6 is), I don't know any compiler that doesn't typedef NULL to Zero, so I always prefer the 2º case .
Regarding your macro approach, I also disagree with it , because IMHO the C++ enum with const variables is a more elegant ,compiler friendly and typesafe manner of defining your errors.
Just my $0,02 in this religious question
Cheers,
Joao Vaz
A person who is nice to you, but rude to the waiter, is not a nice person - Natalie Portman (Padme/Amidala of Star Wars)
|
|
|
|
|
Joao Vaz wrote:
the C++ enum with const variables is a more elegant
You're absolutely correct! I cheated by using a humble macro!
/ravi
Let's try putting "civil" back into "civilization"
http://www.ravib.com
ravib@ravib.com
|
|
|
|
|
Ravi Bhavnani wrote:
I cheated by using a humble macro!
I tend to be a Anti Macro coder , so is why I responded with passion to your approach ...
In IMHO , even ATL that I like , uses and abuses of the macros
Cheers,
Joao Vaz
A person who is nice to you, but rude to the waiter, is not a nice person - Natalie Portman (Padme/Amidala of Star Wars)
|
|
|
|
|
Joao Vaz wrote:
a Standard compiler throws up a std::bad_alloc
Right again! I'd use a try/catch block to catch exceptions.
I guess the point I was trying to make is that it's not safe to treat 0/1 returns as booleans, as they may change to return other values over time, which can lead to hard-to-find bugs.
/ravi
Let's try putting "civil" back into "civilization"
http://www.ravib.com
ravib@ravib.com
|
|
|
|
|
Ravi Bhavnani wrote:
I guess the point I was trying to make is that it's not safe to treat 0/1 returns as booleans, as they may change to return other values over time, which can lead to hard-to-find bugs.
Oh ! okay ... I totally agree with you.
That is the reason why in C# True and False are strongly typed and we are forced to compare with only this pair of values , instead of relying on the 0/1 values
Cheers,
Joao Vaz
A person who is nice to you, but rude to the waiter, is not a nice person - Natalie Portman (Padme/Amidala of Star Wars)
|
|
|
|
|
Joao Vaz wrote:
in C# True and False are strongly typed
Yep, in Java too! Makes for safer code since the compiler won't let you compare an int with a bool .
/ravi
Let's try putting "civil" back into "civilization"
http://www.ravib.com
ravib@ravib.com
|
|
|
|
|
Ravi Bhavnani wrote:
in Java too!
Heh , a Java convert, hein ?
BTW your site is full of humor , quote:
"He's one strange Indian dude..." - Cosmo Kramer
You are indeed a Seinfeld addict
"A pathetic cry for attention - it's deplorable (relatively speaking)" - Albert Einstein
"He's not from Barcelona, is he?" - Basil Fawlty
Cheers,
Joao Vaz
A person who is nice to you, but rude to the waiter, is not a nice person - Natalie Portman (Padme/Amidala of Star Wars)
|
|
|
|
|
Joao Vaz wrote:
Heh , a Java convert, hein ?
Not really, my first love is (and has always been) Windows. But I found some nice concepts in Java when I used it for about 18 months. Now it's on to C# and .Net of which I know absolutely nothing!
Joao Vaz wrote:
your site is full of humor
The product of a warped mind.
/ravi
Let's try putting "civil" back into "civilization"
http://www.ravib.com
ravib@ravib.com
|
|
|
|
|
Ravi Bhavnani wrote:
I guess the point I was trying to make is that it's not safe to treat 0/1 returns as booleans, as they may change to return other values over time, which can lead to hard-to-find bugs.
All right, I got it.
But you must admit that the chance that CompareNoCase() is changed to return a value <>0 for "equal" is rather small, isn't it?
Nevertheless, thanks for the comment.
Geert.
|
|
|
|
|
The problem with using enumerations and constants is that in future versions, if you change either or both, you break previous versions and have to write a lot of extra code to convert them. Using #define's to basically set up integer values that you will interpret later can save you some headaches in the long run.
As for the issue dealing with NULL. That isn't so much the problem. The problem comes when you are trying to debug it is much easier to figure out what is going on when you see something like:
<br />
if (NULL == pFoo)<br />
{<br />
...<br />
}<br />
than
<br />
if (!pFoo)<br />
{<br />
...<br />
}<br />
Just my humble opinion (but I will say that the Bugslayer agrees with me on that
Zac
"If I create everything new, why would I want to delete anything?"
|
|
|
|
|
Zac Howland wrote:
The problem with using enumerations and constants is that in future versions, if you change either or both, you break previous versions and have to write a lot of extra code to convert them. Using #define's to basically set up integer values that you will interpret later can save you some headaches in the long run.
I still prefer the compiler catching my errors than relying on old define ala preprocessor tricks , imho type-safe compiling is worth the trouble , but if you use or have to deal with cross-platorm software then the use of the define within for instance a definition of a facade pattern , since this is transparent to the user , then I'm not against it
<br />
if (!pFoo)<br />
{<br />
...<br />
}<br />
I prefer this only because I'm lazy , and secondly , it implicitily leads me in checking if I initialized the damn pointer
Zac Howland wrote:
Just my humble opinion (but I will say that the Bugslayer agrees with me on that
Yes, I also had read his great book "Debugging Applications" and I use his way of checking variables too:
<br />
if (CONSTANT_X_VALUE == pFoo)<br />
{<br />
...<br />
}<br />
Cheers,Joao Vaz
And if your dream is to care for your family, to put food on the table, to provide them with an education and a good home, then maybe suffering through an endless, pointless, boring job will seem to have purpose. And you will realize how even a rock can change the world, simply by remaining obstinately stationary.-Shog9
Remember just because a good thing comes to an end, doesn't mean that the next one can't be better.-Chris Meech
|
|
|
|
|
Joao Vaz wrote:
I still prefer the compiler catching my errors than relying on old define ala preprocessor tricks , imho type-safe compiling is worth the trouble , but if you use or have to deal with cross-platorm software then the use of the define within for instance a definition of a facade pattern , since this is transparent to the user , then I'm not against it
Type-safe compiling is one thing, but when you are dealing with constants in enumerations, things get hairy when you add something to the enumeration. Lets say I was loading a datafile from a previous version of the application and part of that was an integer value. If the value is part of an enumeration, you can get some very interesting results.
Joao Vaz wrote:
if (!pFoo)
{
...
}
I prefer this only because I'm lazy , and secondly , it implicitily leads me in checking if I initialized the damn pointer
The reason I prefer to do
<br />
if (NULL != pFoo)<br />
{<br />
...<br />
}<br />
is because when I am debugging, it helps to see what value I actually expect to be there. It is just helpful when I get an exception or assertion that throws me back into my source code to know what I am suppose to get instead of what I actually got.
Zac
"If I create everything new, why would I want to delete anything?"
|
|
|
|
|
Zac Howland wrote:
add something to the enumeration. Lets say I was loading a datafile from a previous version of the application and part of that was an integer value. If the value is part of an enumeration, you can get some very interesting results.
Yes, I known , I already had this kind of problems , but I don't honestly remember if I used a define or solved by some other means , chances are if I was in a hurry I sticked with a define.
One point here is that I'm not a religious guy and if for some reason I thought that using a define clearly in some particular situation is the best thing , then ...
BTW the hidden reason why in some cases I used the constant with enumeration is intelisense
Zac Howland wrote:
is because when I am debugging, it helps to see what value I actually expect to be there. It is just helpful when I get an exception or assertion that throws me back into my source code to know what I am suppose to get instead of what I actually got.
Normally I don't need it because I tend to assert a lot at the beginning of the function so :
<br />
ASSERT(pFoo != NULL);<br />
<br />
...<br />
<br />
<br />
if (!pFoo) ...<br />
<br />
The VC++ debugger have also special values for adress that were not initialized , initialized ,just freed and ... so when I simply did known why the pointer was not null
Cheers,Joao Vaz
And if your dream is to care for your family, to put food on the table, to provide them with an education and a good home, then maybe suffering through an endless, pointless, boring job will seem to have purpose. And you will realize how even a rock can change the world, simply by remaining obstinately stationary.-Shog9
Remember just because a good thing comes to an end, doesn't mean that the next one can't be better.-Chris Meech
|
|
|
|
|
Actually, the C++ standards explitly says that NULL can be evaluated as 0 - so the code "if (pFoo)" will allways test the nullity of pFoo. Moreover, the test "if (foo)" is evaluated as "if (foo is not equal to zero)" and not as "if (foo is true)" which makes a vey big difference.
The only problem i can see is the value of the "false" constant. If false is not nul then some problems will arise ; I believe no compiler actually enforces a non-zero value for the C++ false constant and I haven't seen a lib where FALSE (or equivalent) were defined using a non-zero value. I think it is safe to assume FALSE/false to be 0, TRUE/true to be non-zero, NULL to evaluate as 0 and non-zero, non-null, non-false to evaluate accordingly.
But perhaps my experience does not mean anything
Yours,
Emmanuel Deloget
|
|
|
|
|
You're quite right.
The point I was making that it can lead to maintenance headaches for int functions that start out by returning 0 (failure) and 1 (success) and migrate to returning other values for failures. If one is in the habit of not explicitly specifying a boolean condition, you can find yourself in this situation. I learned the hard way .
/ravi
"There is always one more bug..."
http://www.ravib.com
ravib@ravib.com
|
|
|
|
|