tags:

views:

169

answers:

4

Please consider following code:

1.

uint16 a = 0x0001;

if(a < 0x0002)
{
    // do something
}

2.

uint16 a = 0x0001;

if(a < uint16(0x0002))
{
    // do something
}

3.

uint16 a = 0x0001;

if(a < static_cast<uint16>(0x0002))
{
    // do something
}

4.

uint16 a = 0x0001;
uint16 b = 0x0002;

if(a < b)
{
    // do something
}

What compiler does in backgorund and what is the best (and correct) way to do above testing?

p.s. sorry, but I couldn't find the better title :)

EDIT:

values 0x0001 and 0x0002 are only example. There coudl be any 2 byte value instead.

Thank you in advance!

+1  A: 

Since the numbers you're working with are both single digit and less than 10, there's no difference between decimal and hexadecimal. Unless you've defined uint16 in an unexpected way, the cast and/or static_cast should make no difference at all. There should be no real difference between using the constant directly, and initializing a variable, then using that.

What you should be concerned with is making sure that a reader can understand what's going on -- give meaningful names, so it's apparent why you're comparing those items. Since the casts aren't really accomplishing anything, you'd be better off without them.

Jerry Coffin
How's that related to decimal and hexadecimal?
KennyTM
@KennyTM:only that replacing `0x0001` and `0x0002` with just plain `1` and `2` would still work the same way.
Jerry Coffin
+7  A: 

The last example is the best code-wise, as you shouldn't use "magic constants" in your code.

In fact, the best way would be to make b const, (edit) and use meaningful names:

uint16 currentSpeed = 0x0001; 
const uint16 cMaxSpeed = 0x0002; 

if (currentSpeed < cMaxSpeed) 
{ 
    // do something 
} 

Other than that, there is very little difference "under the bonnet" between your examples.

Jason Williams
Yeah, any compiler worth its salt would output the same exact compiled code for those options.
tloflin
And obviously name b something actually descriptive of what it means.
Mark B
@MarkB - Indeed, so obvious I didn't bother pointing it out! I've edited my answer to include this very important point.
Jason Williams
+3  A: 

It is usually best to avoid unnamed "magic" numbers in code, since it is hard for a maintainer to understand what the number is supposed to mean. For this reason, it is good practice to name your constants. For this reason, don't do number 1.

In C++, it is best to use static_cast, rather than C style casts. I'm sure there are probably other questions about why this is the case, but the best reference here is Meyers (Effective C++). For this reason, prefer 3 over 2, but 3 still suffers from the magic number problem.

Four is the best, except the variable names are meaningless, and it might make sense for one or both variables to be const.

I'm not sure if there is any difference between any in terms of compiled code, but there might be due to the literal being interpreted as something other than uint16. It might be a uint32 for instance, although you should still get the expected result.

mch
+2  A: 

If that is all, there's no difference (GCC, -O2). In all cases //do something is simply executed unconditionally.

So it's just a style issue.

UncleBens