Sign in to follow this  
I_Smell_Tuna

Signed and Unsigned

Recommended Posts

It specifies wether or not they use the sign bit. That means you can assign negative values to the signed one, but an unsigned integer can store positive values with "double" the range.

eg: 8 bit integer
unsigned 0 to 255
signed -127 to +127

Share this post


Link to post
Share on other sites
Signed integers can be negative. Unsigned integers can't. (If you try to assign an unsigned integer a negative value it'll "wrap around" and be a really high positive value). Unsigned integers also get to use an extra bit for storing slightly larger numbers than a signed integer, because in a signed integer that bit is used to store the sign of the integer.

Personally, I don't use them but you could use them internally for variables you know will never be negative to reinforce that fact. Also, if you had for example a function f(int x) where the only valid values of x are 0 - 255, instead of checking if(x < 0 || x > 255), if you had f(unsigned int x) you would only have to check if(x > 255), since if x was passed a negative value it'll wrap around to the really high positive value as mentioned previously.

EDIT: Hmm, beaten over the head by 3 posts :0

Share this post


Link to post
Share on other sites
Quote:
Original post by Vampyre_Dark
signed -127 to +127


Nitpick: -128 to 127.

This is because binary numbers hold a power of 2 different values, and there's no reason to allow the representation of both +0 and -0.

Feel free to test it yourself:

#include <cassert>
int main ( void )
{
signed char positive128 = 128;
signed char negative128 = -128;
signed char negative129 = 129;
assert( positive128 < 0 ); //due to wrap around
assert( negative128 < 0 ); //dosn't wrap around
assert( negative129 > 0 ); //due to wrap around
}

Share this post


Link to post
Share on other sites
okay, so ditto above posts.

One thing you'll want to watch out for with unsigneds is decrementing loop counts. In the past I've had to deal with a very common yet bizzare problem that takes a general form:

for(unsigned int i = n; i > 0; i-- )
{ ... }

DON'T do this. The compiler thinks the test case resolves to a == test against zero, which may not be accurate. If you're using a decrementing loop, don't use unsigned's without examining the assembly output to make sure your case is safe.

Share this post


Link to post
Share on other sites
Quote:
Original post by ajas95
okay, so ditto above posts.

One thing you'll want to watch out for with unsigneds is decrementing loop counts. In the past I've had to deal with a very common yet bizzare problem that takes a general form:

for(unsigned int i = n; i > 0; i-- )
{ ... }

DON'T do this. The compiler thinks the test case resolves to a == test against zero, which may not be accurate. If you're using a decrementing loop, don't use unsigned's without examining the assembly output to make sure your case is safe.


Are you sure you wern't smoking anything, and if not, can I have some? :-p.

Kidding aside, that's sane code - it will run the loop with i = N to 1. It'd be an extremely major compiler bug if it didn't. You DO have problems for i >= 0, which is probably what you meant (since this evaluates the same as i < 0, which can never occur for an unsigned). The ugly (but safe) solution to this is to write something like: i > type_of_i(-1).

Share this post


Link to post
Share on other sites
MM, you're surely correct. It was code that had >= in the test expression. But I would never have been able to find it if I didn't know how to read the assembly.

I assumed that because I could do:

for(unsigned int i = 0; i < total; i++)...

I could do:

for(unsigned int i = total - 1; i >= 0; i--)...


I guess the crash makes sense... name me an unsigned int which is NOT >= 0 :)

[edit: tenses]

Share this post


Link to post
Share on other sites
Well, at least gcc issues a warning if a loop condition is always true due to signedness. Probably other compilers do too, at least if you enable warnings.

Share this post


Link to post
Share on other sites

unsigned int x;
x = -1;
printf("%u\n",x);
printf("%i\n",x);

The results are 4294967295 and -1 respectively. The second one MAY issue a compiler warning if you have a savy enough compiler and are using the -Wall -W compile options.

Anyways, the point is in typing, because the two are nearly identical. I say nearly in that I'm not terribly sure if multiplication would yield the same results.

Share this post


Link to post
Share on other sites
Quote:
Original post by MaulingMonkey
Quote:
Original post by Vampyre_Dark
signed -127 to +127


Nitpick: -128 to 127.
[lol] I couldn't remember last night which side got the extra digit, so I let it go.

Share this post


Link to post
Share on other sites
Quote:
Original post by Vampyre_Dark
Quote:
Original post by MaulingMonkey
Quote:
Original post by Vampyre_Dark
signed -127 to +127

Nitpick: -128 to 127.
[lol] I couldn't remember last night which side got the extra digit, so I let it go.

Nitpick: The range of a signed char type is SCHAR_MIN to SCHAR_MAX. The minimum range permitted by the standard is -127 to +127. So Vampyre_Dark's answer was the more accurate option.
Quote:
Original post by bytecoder
Unsigned integers are stored in two's complement; they don't have a "signed" bit.

No, unsigned integers are stored in an unspecified format which may on some machines happen to be two's complement. The only requirement which the standard places upon the representation of unsigned integers is that for numbers which fit in the unsigned and signed variants of a particular integer type, the integers be the same. It is quite possible, and in fact does happen, for integers to have sign bits, be stored in one's complement or something even more exotic.

In addition, although char's sign is up to the compiler, char is neither signed char nor signed char. It is classed as a distinct type which just happens to have the same range as one of the other char types. This should mean that implicit conversions between plain chars and other chars should merit at least a warning. Microsoft Visual C++ doesn't bother issuing a warning for direct assignment, although it does correctly signal an error when assigning a pointer to a char type to a pointer to another char type.

[Edited by - Nathan Baum on May 28, 2005 4:33:09 PM]

Share this post


Link to post
Share on other sites
Quote:
Original post by Nathan Baum
Quote:
Original post by Vampyre_Dark
Quote:
Original post by MaulingMonkey
Quote:
Original post by Vampyre_Dark
signed -127 to +127

Nitpick: -128 to 127.
[lol] I couldn't remember last night which side got the extra digit, so I let it go.

Nitpick: The range of a signed char type is SCHAR_MIN to SCHAR_MAX. The minimum range permitted by the standard is -127 to +127. So Vampyre_Dark's answer was the more accurate option.

Interesting, google says you're right too :-). There any x86 compilers that don't have an SCHAR_MIN of -128? (If not, it would seem the standard is -128, even if this isn't the "official" standard).

VD: I couldn't remember either, so I checked, hence why I actually posted proof [lol].

Share this post


Link to post
Share on other sites
Quote:
Original post by MaulingMonkey
There any x86 compilers that don't have an SCHAR_MIN of -128? (If not, it would seem the standard is -128, even if this isn't the "official" standard).

Assuming that x86 is, in some way, the standard CPU. And obviously assuming that chars are always 8 bits long.

Making assumptions about the architecture is usually a bad idea. Especially in games development, where it's actually fairly realistic to suppose you might at some point be developing for a non-x86 platform.

Share this post


Link to post
Share on other sites
By that argument, -127 through 127 is just as wrong - we're making assumptions again. It could more easily be -2Mi through +2Mi-1.

I feel my point stands, -128 through 127 is extremely common, and I've never seen a system with -127 for SCHAR_MIN. Relying on SCHAR_MIN to be -127 for wrap-around purpouses would be an extremely bad idea because it will almost never happen. One could argue the same for -128, I won't disagree, but at least it'll work for SOME architectures.

Share this post


Link to post
Share on other sites
Quote:
Original post by MaulingMonkey
By that argument, -127 through 127 is just as wrong - we're making assumptions again. It could more easily be -2Mi through +2Mi-1.

No you're not. If the Standard says -127 to 127 is the minimum allowed range, then you aren't assuming anything. Its right there in the text, the miminum allowed range is -127 to 127. If it also says that the actual range is represented by SCHAR_MIN to SCHAR_MAX, then you again aren't assuming anything. The actual range is SCHAR_MIN to SCHAR_MAX.

I use numeric_limits<T> myself. Easier to remember.

CM

Share this post


Link to post
Share on other sites
Quote:
Original post by Conner McCloud
Quote:
Original post by MaulingMonkey
By that argument, -127 through 127 is just as wrong - we're making assumptions again. It could more easily be -2Mi through +2Mi-1.

No you're not.


Let me be more explicit - You're not if you're explicitly not talking about the complete, full range of signed char. If you're talking about the complete, full range of a signed char, then it's an assumption.

When you talk about how fast a car can go, you don't say "My Ferrarri can go 10mph" when it can go 160mph (I'm no car expert, so deal with it if that number is off). You say "My Ferrarri can go 160mph", people are probably going to assume that's the maximum speed.

Similarly, one could say "signed char can cover the range [-3 .. +3]". Completely accurate - as long as you're not giving the impression that you can't store -4 or +4 as well.

I'm addressing the point where Nathan Baum states that Vampyre_Dark is somehow more accurate, when Vampyre_Dark made no mention of SCHAR_MIN, SCHAR_MAX, numeric_limits, etc, and left it completely unspecified if this was the full range, minimum standard full range, etc. Personally, when someone states a range like that, I take it to mean "this is the full range that ____ can cover". If I were Random N. Ewbie, heard about how overflow usually works, and assumed this, I'd think "So, if I try and assign 128 to a signed char, I'll get -127 right?" - which would be wrong.

I thought this was fairly obviously implied from my example assumption about overflows, but it apparently not.

Share this post


Link to post
Share on other sites
Quote:
Original post by MaulingMonkey
When you talk about how fast a car can go, you don't say "My Ferrarri can go 10mph" when it can go 160mph (I'm no car expert, so deal with it if that number is off). You say "My Ferrarri can go 160mph", people are probably going to assume that's the maximum speed.

There are any number of cases where you might say "my ferarri can go 10mph" even though it can also go at 160mph.

Let's assume that the minimum maximum speed of any car is 60mph. If somebody asks "what's the maximum speed of a car", which is more accurate: 60mph or 160mph? Obviously the most accurate response wouldn't be either of them, but I think there's a clear conceptual difference between giving an answer which is within the speed ranges of all cars and giving one that is out of the range of some. I think the answer 60mph would somehow be more accurate, because all cars can at least achieve that speed.
Quote:

I'm addressing the point where Nathan Baum states that Vampyre_Dark is somehow more accurate, when Vampyre_Dark made no mention of SCHAR_MIN, SCHAR_MAX, numeric_limits, etc, and left it completely unspecified if this was the full range, minimum standard full range, etc.

You said signed chars have the range -128 to 127. According to the standard, that is a false statement to make. They don't necessarily support all values in that range.

He said signed chars have the range -127 to 127. According to the standard, that is a true statement to make. They necessarily support all values in that range.

Vampyre_Dark obviously meant the full range, so he was wrong. But, if one wrote well-formed programs on the basis that the full range of signed chars was -127 to 127, they would be guaranteed to work on all compliant implementaions. Whilst assuming a range of -128 to 127 wouldn't have the same guarantee.

The range of a signed char is either [ -127, 127 ] or [ SCHAR_MIN, SCHAR_MAX ]. No other statement of the range of a signed char is accurate without qualification of which implementation you are referring to.
Quote:

Personally, when someone states a range like that, I take it to mean "this is the full range that ____ can cover". If I were Random N. Ewbie, heard about how overflow usually works, and assumed this, I'd think "So, if I try and assign 128 to a signed char, I'll get -127 right?" - which would be wrong.

If you knew about how overflow worked according to the standard, you'd know that the behaviour of a signed type upon receiving a value that is out of range is undefined. The question of whether or not there is bounds checking on signed integer types is left up to the implementation to decide.

This is the whole problem with C/C++ portability. Students are taught that "all the world's an IBM compatible". Instead of being told that the range of a signed char is at least -127 to 127, and more precisely SCHAR_MIN to SCHAR_MAX, they are told it's -128 to 127 and may potentially have to unlearn that if they do some programming for an unusual architecture.

Share this post


Link to post
Share on other sites
Quote:
Original post by Nathan Baum
Quote:
Original post by MaulingMonkey
When you talk about how fast a car can go, you don't say "My Ferrarri can go 10mph" when it can go 160mph (I'm no car expert, so deal with it if that number is off). You say "My Ferrarri can go 160mph", people are probably going to assume that's the maximum speed.

There are any number of cases where you might say "my ferarri can go 10mph" even though it can also go at 160mph.


In specific contexts yes. Without context - I'd give whoever suddenly stated "my ferarri can go 10mph" a very odd look, and probably inquire about what prompted such a... wonderful relevation?

Quote:
You said signed chars have the range -128 to 127. According to the standard, that is a false statement to make. They don't necessarily support all values in that range.

He said signed chars have the range -127 to 127. According to the standard, that is a true statement to make. They necessarily support all values in that range.

Vampyre_Dark obviously meant the full range, so he was wrong.


Which has been my point which I've been repeatedly rehashing - that, in terms of the full range, -128 to 127 is by far more common than -127 to 127, although neither is correct in terms of the standard. Enough said :-).

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this