423,867 Members | 1,958 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 423,867 IT Pros & Developers. It's quick & easy.

signed vs unsigned

P: n/a
LuB
This isn't a C++ question per se ... but rather, I'm posting this bcs I
want the answer from a C++ language perspective. Hope that makes sense.

I was reading Peter van der Linden's "Expert C Programming: Deep C
Secrets" and came across the following statement:

"Avoid unnecessary complexity by minimizing your use of unsigned types.
Specifically, don't use an unsigned type to represent a quantity just
because it will never be negative (e.g., "age" or "national_debt")."

Admittedly, I minimize comments in my code. I use them when necessary
but try to limit them to one or two lines. I just don't like their
aesthetic affect in the source. I find the code much harder to read
littered with paragraphs of explanations.

I find the code easier to read when broken up with appropriate newlines
and small, short comments acting as headings.

So - that effectually means that I try my darndest to write
self-describing code. Shorter functions, self-explanatory names for
functions and variable names, etc. Sometimes exceessive commenting is
necessary, but as a whole, I tend to avoid it.

I'm really enjoying Peter's book, but I find this comment hard to
swallow considering that if an age or array index can never be negative
- I would want to illustrate that with an apporpriate choice of type -
namely, unsigned int.

Am I in the minority here? Is my predilection considered poor style?

I guess, from the compiler's standpoint ... using int everywhere is
more portable ... since comparison's against unsigned int can vary
between K&R and ANSI C.

I'm not incurring some type of performance penalty for such decisions
am I?

Thanks in advance,

-Luther

Feb 21 '06 #1
Share this Question
Share on Google+
26 Replies


P: n/a
On 21 Feb 2006 08:58:23 -0800, "LuB" <lu*********@yahoo.com> wrote:
I'm really enjoying Peter's book, but I find this comment hard to
swallow considering that if an age or array index can never be negative
- I would want to illustrate that with an apporpriate choice of type -
namely, unsigned int.

Am I in the minority here?
Hopefully not!
Is my predilection considered poor style?


Absolutely not!

The key to dealing with signed vs. unsigned is not to mix them, if
possible, in comparisons. Be especially wary of comparing an unsigned
counter value to 0 while decrementing the counter.

--
Bob Hairgrove
No**********@Home.com
Feb 21 '06 #2

P: n/a
Like you said, marking a type as "unsigned" if for nothing else is an
easy documentation for other developers that it will never be negative.
I havn't read his stuff but I can't imagine what complexities he is
talking about.

Performance differences depend largly on your architecture. On AMD64,
division/modulus are faster when using unsigned types. Conversion to
floating point is faster with signed types. Addition/subtraction are
the same.

Feb 21 '06 #3

P: n/a

LuB wrote:
I'm really enjoying Peter's book, but I find this comment hard to
swallow considering that if an age or array index can never be negative
- I would want to illustrate that with an apporpriate choice of type -
namely, unsigned int.


The only reason that I can think of that you might want to not use
'unsigned' is if the assumption that it will never be negative might
change. However, most times you are better off with the assumption and
the protection of the unsigned type and then change it later if you
have to. Minimize dependencies on the type so that it is easier to do.

The great thing about unsigned is if the value can't be negative and
you use signed then you always have to check it. Simply defining the
type as unsigned gets rid of all that as well as documenting your
domain.

Feb 21 '06 #4

P: n/a
LuB posted:
This isn't a C++ question per se ... but rather, I'm posting this bcs I
want the answer from a C++ language perspective. Hope that makes sense.

I was reading Peter van der Linden's "Expert C Programming: Deep C
Secrets" and came across the following statement:

"Avoid unnecessary complexity by minimizing your use of unsigned types.
Specifically, don't use an unsigned type to represent a quantity just
because it will never be negative (e.g., "age" or "national_debt")."

Admittedly, I minimize comments in my code. I use them when necessary
but try to limit them to one or two lines. I just don't like their
aesthetic affect in the source. I find the code much harder to read
littered with paragraphs of explanations.

I find the code easier to read when broken up with appropriate newlines
and small, short comments acting as headings.

So - that effectually means that I try my darndest to write
self-describing code. Shorter functions, self-explanatory names for
functions and variable names, etc. Sometimes exceessive commenting is
necessary, but as a whole, I tend to avoid it.

I'm really enjoying Peter's book, but I find this comment hard to
swallow considering that if an age or array index can never be negative
- I would want to illustrate that with an apporpriate choice of type -
namely, unsigned int.

Am I in the minority here? Is my predilection considered poor style?

I guess, from the compiler's standpoint ... using int everywhere is
more portable ... since comparison's against unsigned int can vary
between K&R and ANSI C.

I'm not incurring some type of performance penalty for such decisions
am I?

Thanks in advance,

-Luther

My first rule is to write "const" wherever I can.
(except for return types).

My second rule is to write "unsigned" wherever I can.
Thus I'll write:

unsigned GetDogAge(unsigned const age)
{
return age * 7;
}

Or alternatively re-use the parameter variable:

unsigned GetDogAge(unsigned age)
{
return age *= 7;
}
-Tomás
Feb 21 '06 #5

P: n/a
In article <11**********************@f14g2000cwb.googlegroups .com>,
ro**********@gmail.com wrote:
The great thing about unsigned is if the value can't be negative and
you use signed then you always have to check it. Simply defining the
type as unsigned gets rid of all that as well as documenting your
domain.


And the bad thing about unsigned is that if code would otherwise make
the value negative, you can't check it. IE

void foo( unsigned s ) {
// at this point s == 4294966272
// is it an error (s came in as -1024) or
// does the client really want us to deal with that number?
}

Bjarne Stroustrup says, "The unsigned integer types are ideal for uses
that treat storage as a bit array. Using an unsigned instead of an int
to gain one more bit to represent positive integers is almost never a
good idea. Attempts to ensure that some values are positive by declaring
variables unsigned will typically be defeated by the implicit conversion
rules."

--
Magic depends on tradition and belief. It does not welcome observation,
nor does it profit by experiment. On the other hand, science is based
on experience; it is open to correction by observation and experiment.
Feb 21 '06 #6

P: n/a

Tomás wrote:
Or alternatively re-use the parameter variable:

unsigned GetDogAge(unsigned age)
{
return age *= 7;
}


Performs an unnecissary and unused assignment as age is automatic and
will be gone after return.

Feb 21 '06 #7

P: n/a

LuB wrote:
This isn't a C++ question per se ... but rather, I'm posting this bcs I
want the answer from a C++ language perspective. Hope that makes sense.

I was reading Peter van der Linden's "Expert C Programming: Deep C
Secrets" and came across the following statement:

"Avoid unnecessary complexity by minimizing your use of unsigned types.
Specifically, don't use an unsigned type to represent a quantity just
because it will never be negative (e.g., "age" or "national_debt")."
<snip> -Luther


Well, it is a style issue, so many people will probably disagree with
me. They are probably all right, and I would still be able to respect
them :)

That said, I personally use signed types almost all the time, even if
something should never be negative. Every once in a while, I make a
horribly stupid error in something like a file loading function.
Suppose an object can have zero or more child objects. If my loader
returns an object that claims to have -1024 children, then I know I've
done something wrong, and it can be easier to track down bugs that
compile and don't crash. If it just claims that there are a large
positive number of children, it's not as easy to catch the error
condition. There is even the wildly unlikely possibility that there is
an error due to a hardware fault like bad RAM. (Though, the problems
are almost always caused by me! Many people who are better programmers
than me may find that hardware accounts for a greater percentage of
problems than I do :)

Also, I use negative values as intentional error codes and special
cases. Some people consider this horrible style. I can respect that.
But, for a lot of the things I do, it is the quickest, easiest,
simplest, and clearest way to have a recoverable error. So, my
hypothetical object loading function might return an object which
claims -1 children if it failed to open the file, -2 if it failed to
parse the file, -3 if the file contained invalid information, etc. I
know, exceptions are probably better for most of these things, but my
personal style is to write C++ that looks a lot like C, and uses
occasional C++ features. It's just more inline with the way I think
about the problems.

Also, by always using signed types, I can avoid comparisons between
signed and unsigned. It is also generally easier to catch overflow.
After all, the national debt might never be negative, but it certainly
might exceed MAX_INT on some systems! :)

I tend to work alone on personal projects. So, the most important
thing for me is that my personal coding style is readable - to me.
Feel free to strongly disagree with my style.

Feb 21 '06 #8

P: n/a
On 2006-02-21, Tomás <NU**@NULL.NULL> wrote:
My first rule is to write "const" wherever I can.
(except for return types).

My second rule is to write "unsigned" wherever I can.
I don't agree with that rule.
Thus I'll write:

unsigned GetDogAge(unsigned const age)
{
return age * 7;
}


What do you expect to happen if a client passes in an negative int?

The argument is not in the domain, yet the error has been rendered
impossible to detect or recover from.

--
Neil Cerutti
Feb 21 '06 #9

P: n/a
* Neil Cerutti:
On 2006-02-21, Tomás <NU**@NULL.NULL> wrote:
My first rule is to write "const" wherever I can.
(except for return types).

My second rule is to write "unsigned" wherever I can.


I don't agree with that rule.
Thus I'll write:

unsigned GetDogAge(unsigned const age)
{
return age * 7;
}


What do you expect to happen if a client passes in an negative int?

The argument is not in the domain, yet the error has been rendered
impossible to detect or recover from.


I don't disagree with your viewpoint regarding using or not using
unsigned whenever possible; I think both are valid viewpoints, and as
with indentation the main thing is to be consistent in one's choices.

However, I disagree with your reason!

With the unsigned argument a validity test might go like

assert( age < 200 ); // unsigned validity test.

With a signed argument the test might go like

assert( age >= 0 ); // signed validity test.
assert( age < 200 ); // more signed validity test.

Now, first of all that demonstrates the "impossible to detect" is simply
incorrect, and second, in my view it demonstrates a slight superiority
for unsigned in this particular case, with respect to validity testing.

Cheers,

- Alf

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Feb 21 '06 #10

P: n/a

Alf P. Steinbach wrote:
* Neil Cerutti:
On 2006-02-21, Tomás <NU**@NULL.NULL> wrote:
My first rule is to write "const" wherever I can.
(except for return types).

My second rule is to write "unsigned" wherever I can.


I don't agree with that rule.
Thus I'll write:

unsigned GetDogAge(unsigned const age)
{
return age * 7;
}


What do you expect to happen if a client passes in an negative int?

The argument is not in the domain, yet the error has been rendered
impossible to detect or recover from.


I don't disagree with your viewpoint regarding using or not using
unsigned whenever possible; I think both are valid viewpoints, and as
with indentation the main thing is to be consistent in one's choices.

However, I disagree with your reason!

With the unsigned argument a validity test might go like

assert( age < 200 ); // unsigned validity test.

With a signed argument the test might go like

assert( age >= 0 ); // signed validity test.
assert( age < 200 ); // more signed validity test.

Now, first of all that demonstrates the "impossible to detect" is simply
incorrect, and second, in my view it demonstrates a slight superiority
for unsigned in this particular case, with respect to validity testing.


I believe he is talking about something like this:
#include <iostream>
using namespace std;

unsigned int GetDogAge(unsigned int age)
{
return age * 7;
}

int main(int argc, char* argv[])
{
int t = -5;
unsigned int x = GetDogAge(t);

cout << x;

int y; cin >> y;

return 0;
}

------ Build started: Project: Playground, Configuration: Debug Win32
------

Compiling...
Playground.cpp
Linking...

Build log was saved at
"file://c:\src\Playground\Playground\Debug\BuildLog.htm"
Playground - 0 error(s), 0 warning(s)
---------------------- Done ----------------------

Build: 1 succeeded, 0 failed, 0 skipped

Output is, "4294967261."

It is an interesting point.

Feb 21 '06 #11

P: n/a
Daniel T. wrote:
In article <11**********************@f14g2000cwb.googlegroups .com>,
ro**********@gmail.com wrote:
The great thing about unsigned is if the value can't be negative and
you use signed then you always have to check it. Simply defining the
type as unsigned gets rid of all that as well as documenting your
domain.
And the bad thing about unsigned is that if code would otherwise make
the value negative, you can't check it. IE

void foo( unsigned s ) {
// at this point s == 4294966272
// is it an error (s came in as -1024) or
// does the client really want us to deal with that number?
}

Bjarne Stroustrup says, "The unsigned integer types are ideal for uses
that treat storage as a bit array. Using an unsigned instead of an int
to gain one more bit to represent positive integers is almost never a
good idea. Attempts to ensure that some values are positive by declaring
variables unsigned will typically be defeated by the implicit conversion
rules."


Sounds like a good excuse to write an unsigned_int class:

#include <boost/utility/enable_if.hpp>
#include <boost/numeric/conversion/converter.hpp>
#include <boost/type_traits/is_unsigned.hpp>

class unsigned_int{
unsigned int m_value;
public:
template <typename T>
unsigned_int(T const & rhs,
typename boost::enable_if<
boost::is_unsigned<T>,
void*::type = 0

)
{
// further features
// throws on overflow when T is bigger eg unsigned long
boost::numeric::converter<unsigned int,T> convert;
m_value = convert(rhs);
}
};

int main()
{
unsigned_int n1 = 1U;
unsigned_int n2 = static_cast<unsigned short>(1);
unsigned_int n3 = 1UL;
unsigned_int n4 = static_cast<unsigned int>(1);

unsigned_int n5 = 1; // Error!
}

reagrds
Andy Little

Feb 21 '06 #12

P: n/a

Daniel T. wrote:
In article <11**********************@f14g2000cwb.googlegroups .com>,
ro**********@gmail.com wrote:
The great thing about unsigned is if the value can't be negative and
you use signed then you always have to check it. Simply defining the
type as unsigned gets rid of all that as well as documenting your
domain.
And the bad thing about unsigned is that if code would otherwise make
the value negative, you can't check it. IE

void foo( unsigned s ) {
// at this point s == 4294966272
// is it an error (s came in as -1024) or
// does the client really want us to deal with that number?
}

Bjarne Stroustrup says, "The unsigned integer types are ideal for uses
that treat storage as a bit array. Using an unsigned instead of an int
to gain one more bit to represent positive integers is almost never a
good idea. Attempts to ensure that some values are positive by declaring
variables unsigned will typically be defeated by the implicit conversion
rules."


Sounds like a good excuse for an unsigned_int class ...

#include <boost/utility/enable_if.hpp>
#include <boost/numeric/conversion/converter.hpp>
#include <boost/type_traits/is_unsigned.hpp>

class unsigned_int{
unsigned int m_value;
public:
template <typename T>
unsigned_int(T const & rhs,
typename boost::enable_if<
boost::is_unsigned<T>,
void*::type = 0

)
{
// further features
// throws on overflow when T is bigger eg unsigned long
boost::numeric::converter<unsigned int,T> convert;
m_value = convert(rhs);
}
};

int main()
{
unsigned_int n1 = 1U;
unsigned_int n2 = static_cast<unsigned short>(1);
unsigned_int n3 = 1UL;
unsigned_int n4 = static_cast<unsigned int>(1);

unsigned_int n5 = 1; // Error!
}

reagrds
Andy Little

Feb 21 '06 #13

P: n/a
Daniel T. wrote:
In article <11**********************@f14g2000cwb.googlegroups .com>,
ro**********@gmail.com wrote:
The great thing about unsigned is if the value can't be negative and
you use signed then you always have to check it. Simply defining the
type as unsigned gets rid of all that as well as documenting your
domain.
And the bad thing about unsigned is that if code would otherwise make
the value negative, you can't check it. IE

void foo( unsigned s ) {
// at this point s == 4294966272
// is it an error (s came in as -1024) or
// does the client really want us to deal with that number?
}

Bjarne Stroustrup says, "The unsigned integer types are ideal for uses
that treat storage as a bit array. Using an unsigned instead of an int
to gain one more bit to represent positive integers is almost never a
good idea. Attempts to ensure that some values are positive by declaring
variables unsigned will typically be defeated by the implicit conversion
rules."


Sounds like a good excuse to write an unsigned_int class:

#include <boost/utility/enable_if.hpp>
#include <boost/numeric/conversion/converter.hpp>
#include <boost/type_traits/is_unsigned.hpp>

class unsigned_int{
unsigned int m_value;
public:
template <typename T>
unsigned_int(T const & rhs,
typename boost::enable_if<
boost::is_unsigned<T>,
void*::type = 0

)
{
// further features
// throws on overflow when T is bigger eg unsigned long
boost::numeric::converter<unsigned int,T> convert;
m_value = convert(rhs);
}
};

int main()
{
unsigned_int n1 = 1U;
unsigned_int n2 = static_cast<unsigned short>(1);
unsigned_int n3 = 1UL;
unsigned_int n4 = static_cast<unsigned int>(1);

unsigned_int n5 = 1; // Error!
}

reagrds
Andy Little

Feb 21 '06 #14

P: n/a

a...@servocomm.freeserve.co.uk wrote:

Sorry
Sorry
Sorry for posting 3 times. Browser hung up

regards
Andy Little

Feb 21 '06 #15

P: n/a
* ro**********@gmail.com:
Alf P. Steinbach wrote:
* Neil Cerutti:
On 2006-02-21, Tomás <NU**@NULL.NULL> wrote:
My first rule is to write "const" wherever I can.
(except for return types).

My second rule is to write "unsigned" wherever I can.
I don't agree with that rule.

Thus I'll write:

unsigned GetDogAge(unsigned const age)
{
return age * 7;
}
What do you expect to happen if a client passes in an negative int?

The argument is not in the domain, yet the error has been rendered
impossible to detect or recover from. I don't disagree with your viewpoint regarding using or not using
unsigned whenever possible; I think both are valid viewpoints, and as
with indentation the main thing is to be consistent in one's choices.

However, I disagree with your reason!

With the unsigned argument a validity test might go like

assert( age < 200 ); // unsigned validity test.

With a signed argument the test might go like

assert( age >= 0 ); // signed validity test.
assert( age < 200 ); // more signed validity test.

Now, first of all that demonstrates the "impossible to detect" is simply
incorrect, and second, in my view it demonstrates a slight superiority
for unsigned in this particular case, with respect to validity testing.


I believe he is talking about something like this:

[snip] int t = -5;
unsigned int x = GetDogAge(t);


Yes, that would be caught by the validity test for unsigned formal arg,

assert( age < 200 );

Cheers,

- Alf
--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Feb 21 '06 #16

P: n/a
LuB wrote:
This isn't a C++ question per se ... but rather, I'm posting this bcs I
want the answer from a C++ language perspective. Hope that makes sense.

I was reading Peter van der Linden's "Expert C Programming: Deep C
Secrets" and came across the following statement:

"Avoid unnecessary complexity by minimizing your use of unsigned types.
Specifically, don't use an unsigned type to represent a quantity just
because it will never be negative (e.g., "age" or "national_debt")."

Admittedly, I minimize comments in my code. I use them when necessary
but try to limit them to one or two lines. I just don't like their
aesthetic affect in the source. I find the code much harder to read
littered with paragraphs of explanations.

I find the code easier to read when broken up with appropriate newlines
and small, short comments acting as headings.

So - that effectually means that I try my darndest to write
self-describing code. Shorter functions, self-explanatory names for
functions and variable names, etc. Sometimes exceessive commenting is
necessary, but as a whole, I tend to avoid it.

I'm really enjoying Peter's book, but I find this comment hard to
swallow considering that if an age or array index can never be negative
- I would want to illustrate that with an apporpriate choice of type -
namely, unsigned int.

Am I in the minority here? Is my predilection considered poor style?

I guess, from the compiler's standpoint ... using int everywhere is
more portable ... since comparison's against unsigned int can vary
between K&R and ANSI C.

I'm not incurring some type of performance penalty for such decisions
am I?

Thanks in advance,

-Luther
It's like driving on the left or driving on the right. It's basically
an
arbitrary choice (now that we drive cars), it's just good if everyone
makes the same arbitrary choice. That is if there's more than
just you on the road, which is analagous to maintaining
existing code or heavily using libraries written by others.

Many compilers generate (to me helpful) warnings if you do a, <, <=, >= comparison between a signed and unsigned.

Many also generate (to me useless) warnings if you do a
== or != comparison between a signed and unsigned. So,
you can end up with alot of static_casts to get rid of the
warnings.

For some reason, if an unsigned type is used in an expression
where it has to be implicitly converted to a larger type, it
will be converted to a signed larger type. As far as I can
see, this rule has no practical effect, other than to give
some compilers an excuse to generate unnecessary
warnings. (I guess it could change the results when
using bitwise ops on variables of different sizes, which
to me is a bad idea anyway.) So, that's one reason to prefer
signed. But, like you, I prefer to use unsigned for variables that
should always be nonnegative, to make the intent clear.

Feb 21 '06 #17

P: n/a
Daniel T. wrote:
In article <11**********************@f14g2000cwb.googlegroups .com>,
ro**********@gmail.com wrote:
The great thing about unsigned is if the value can't be negative and
you use signed then you always have to check it. Simply defining the
type as unsigned gets rid of all that as well as documenting your
domain.


And the bad thing about unsigned is that if code would otherwise make
the value negative, you can't check it. IE


Surely overflow and underflow are a problem with both signed and unsigned?

These are often situations where you are unable to check validity
without domain specific knowledge - I don't see how signed unsigned vary
in that regard.

Ben Pope
--
I'm not just a number. To many, I'm known as a string...
Feb 22 '06 #18

P: n/a

LuB wrote:
This isn't a C++ question per se ... but rather, I'm posting this bcs I
want the answer from a C++ language perspective. Hope that makes sense.

I was reading Peter van der Linden's "Expert C Programming: Deep C
Secrets" and came across the following statement:

"Avoid unnecessary complexity by minimizing your use of unsigned types.
Specifically, don't use an unsigned type to represent a quantity just
because it will never be negative (e.g., "age" or "national_debt")."

Admittedly, I minimize comments in my code. I use them when necessary
but try to limit them to one or two lines. I just don't like their
aesthetic affect in the source. I find the code much harder to read
littered with paragraphs of explanations.

I find the code easier to read when broken up with appropriate newlines
and small, short comments acting as headings.

So - that effectually means that I try my darndest to write
self-describing code. Shorter functions, self-explanatory names for
functions and variable names, etc. Sometimes exceessive commenting is
necessary, but as a whole, I tend to avoid it.
Self-explanatory names are good.
I'm really enjoying Peter's book, but I find this comment hard to
swallow considering that if an age or array index can never be negative
- I would want to illustrate that with an apporpriate choice of type -
namely, unsigned int.
Why would you want to illustrate it with an appropriate choice of type?
I would want to illustrate it with a self-explanatory name.
Am I in the minority here? Is my predilection considered poor style?

I guess, from the compiler's standpoint ... using int everywhere is
more portable ... since comparison's against unsigned int can vary
between K&R and ANSI C.

I'm not incurring some type of performance penalty for such decisions
am I?


This question comes up regularly. Search the history of the newsgroup
and you will find plenty of discussion. But I am slightly surprised to
see this thread get to nearly 20 posts (as far as I can see so far)
without anyone mentioning the subtraction issue.

Personally, I do not accept that argument for unsigned as documentation
to mean "negative values make no sense here". The variable name (age,
buffer_size, radius) serves that purpose. Comparison with const is not
valid. const is useful because it is enforced by the compiler. unsigned
is not enforced. -1 years does not make sense for age, but neither does
4294967295 years. At best, using unsigned has only documented one end
of your range. And since the variable name has already achieved that,
you haven't gained anything.

But that's not the only reason I don't use unsigned for these sort of
quantities. In general, subtracting one person's age from another in
the real world yields a signed result but in C++ subtracting one
unsigned quantity from another yields an unsigned result.

<quote Kaz Kylheku (in post number 28 as I write this)>
http://groups.google.co.uk/group/com...236f41f9de66f8

Thus code like if (buffer_space - requested_payload > header_size)
is broken if unsigned integers are used, and there was no prior check
that the requested_payload isn't larger than the buffer.

</quote>

Both signed and unsigned arithmetic in C++ behave just like real world
integer arithmetic until you reach the minimum and maximum values for
those types. The difference is that for signed, the correlation between
the real world and C++ breaks down at + or - a very big number, whereas
for unsigned, the correlation between the real world and C++ breaks
down at zero and a (different) very big number.

In other words, if I use unsigned, I am very close to the edge of the
domain in which C++ arithmetic corresponds to the real world. If I use
signed, I am comfortably in the middle of that domain and the
extremities where I have to start coding for special cases are far, far
away from any number that I am likely to ever want to use for an age or
a length or a size, or I am likely to ever end up with by doing
arithmetic with those quantities.

Gavin Deane

Feb 22 '06 #19

P: n/a
Gavin Deane wrote:

But that's not the only reason I don't use unsigned for these sort of
quantities. In general, subtracting one person's age from another in
the real world yields a signed result but in C++ subtracting one
unsigned quantity from another yields an unsigned result.

<quote Kaz Kylheku (in post number 28 as I write this)>
http://groups.google.co.uk/group/com...236f41f9de66f8

Thus code like if (buffer_space - requested_payload > header_size)
is broken if unsigned integers are used, and there was no prior check
that the requested_payload isn't larger than the buffer.

</quote>
That's a very good point.
Both signed and unsigned arithmetic in C++ behave just like real world
integer arithmetic until you reach the minimum and maximum values for
those types. The difference is that for signed, the correlation between
the real world and C++ breaks down at + or - a very big number, whereas
for unsigned, the correlation between the real world and C++ breaks
down at zero and a (different) very big number.

In other words, if I use unsigned, I am very close to the edge of the
domain in which C++ arithmetic corresponds to the real world. If I use
signed, I am comfortably in the middle of that domain and the
extremities where I have to start coding for special cases are far, far
away from any number that I am likely to ever want to use for an age or
a length or a size, or I am likely to ever end up with by doing
arithmetic with those quantities.


In an ideal world, we would probably all do range checking more often
than we do.

I always say you make your own luck, with signed types you're more lucky!

Ben Pope
--
I'm not just a number. To many, I'm known as a string...
Feb 22 '06 #20

P: n/a

Gavin Deane wrote:

<snip>
Personally, I do not accept that argument for unsigned as documentation
to mean "negative values make no sense here". The variable name (age,
buffer_size, radius) serves that purpose.


<snip>

Hmmm.... Not sure why I'd want an integer, signed or otherwise, for a
radius. That would be a floating point type. Replace that with a more
sensible quantity - number of clients connected to the server, or
number of pigs on the farm or something.

Gavin Deane

Feb 22 '06 #21

P: n/a
On 2006-02-21, Alf P. Steinbach <al***@start.no> wrote:
* Neil Cerutti:
On 2006-02-21, Tomás <NU**@NULL.NULL> wrote:
My first rule is to write "const" wherever I can.
(except for return types).

My second rule is to write "unsigned" wherever I can.
I don't agree with that rule.
Thus I'll write:

unsigned GetDogAge(unsigned const age)
{
return age * 7;
}


What do you expect to happen if a client passes in an negative int?

The argument is not in the domain, yet the error has been rendered
impossible to detect or recover from.


I don't disagree with your viewpoint regarding using or not using
unsigned whenever possible; I think both are valid viewpoints, and
as with indentation the main thing is to be consistent in one's
choices.

However, I disagree with your reason!

With the unsigned argument a validity test might go like

assert( age < 200 ); // unsigned validity test.


That will help when the domain doesn't include all positive
representable integers, yes. You assumed a domain restriction that was
not in evidence. ;-)
With a signed argument the test might go like

assert( age >= 0 ); // signed validity test.
assert( age < 200 ); // more signed validity test.
I much prefer your second example, but perhaps that's a matter of
taste. Moreover, I don't want or need to learn the rules for unsigned
arithmetic if I only use them for their bit-values.
Now, first of all that demonstrates the "impossible to detect" is
simply incorrect, and second, in my view it demonstrates a slight
superiority for unsigned in this particular case, with respect to
validity testing.


Yes, I should have been more specific.

--
Neil Cerutti
Feb 22 '06 #22

P: n/a
On 2006-02-22, Ben Pope <be***************@gmail.com> wrote:
Daniel T. wrote:
In article <11**********************@f14g2000cwb.googlegroups .com>,
ro**********@gmail.com wrote:
The great thing about unsigned is if the value can't be negative
and you use signed then you always have to check it. Simply
defining the type as unsigned gets rid of all that as well as
documenting your domain. >> >> And the bad thing about unsigned
is that if code would otherwise make >> the value negative, you
can't check it. IE > > Surely overflow and underflow are a problem
with both signed and unsigned?


These are often situations where you are unable to check validity
without domain specific knowledge - I don't see how signed unsigned
vary in that regard.


Because a signed negative value will be silently converted to a
positive unsigned value. I suppose this works both ways, though. I
can't prevent someone from passing a positive unsigned value to my
signed function, yielding the same problem in the mirror.

--
Neil Cerutti
Feb 22 '06 #23

P: n/a
On Wed, 22 Feb 2006 10:34:20 +0000, Ben Pope
<be***************@gmail.com> wrote:
Daniel T. wrote:
In article <11**********************@f14g2000cwb.googlegroups .com>,
ro**********@gmail.com wrote:
The great thing about unsigned is if the value can't be negative and
you use signed then you always have to check it. Simply defining the
type as unsigned gets rid of all that as well as documenting your
domain.
And the bad thing about unsigned is that if code would otherwise make
the value negative, you can't check it. IE


Surely overflow and underflow are a problem with both signed and unsigned?


They are a problem with signed (undefined or non-portable behavior),
but behavior with unsigned is well-defined by the standard (values
wrap). There is never any true overflow with unsigned integral values.
These are often situations where you are unable to check validity
without domain specific knowledge - I don't see how signed unsigned vary
in that regard.

Ben Pope


--
Bob Hairgrove
No**********@Home.com
Feb 22 '06 #24

P: n/a
Bob Hairgrove wrote:
On Wed, 22 Feb 2006 10:34:20 +0000, Ben Pope
<be***************@gmail.com> wrote:
Surely overflow and underflow are a problem with both signed and unsigned?


They are a problem with signed (undefined or non-portable behavior),
but behavior with unsigned is well-defined by the standard (values
wrap). There is never any true overflow with unsigned integral values.


I guess that depends on your definition of overflow, in the context
provided I would class the following as overflow (on a platform with 8
bit char):

#include <iostream>

int main() {
unsigned char val = 128;
val *= 2; // overflow
std::cout << static_cast<unsigned int>(val) << "\n";
val = 0;
val -= 1; // underflow?
std::cout << static_cast<unsigned int>(val);
}

The behaviour may well be defined, but but I would call it overflow,
nonetheless.

I'm not sure if underflow is the correct term for the second "problem",
but that's what I call it.

Ben Pope
--
I'm not just a number. To many, I'm known as a string...
Feb 22 '06 #25

P: n/a

"Neil Cerutti" <le*******@email.com> skrev i meddelandet
news:sl*********************@FIAD06.norwich.edu...
On 2006-02-22, Ben Pope <be***************@gmail.com> wrote:
Daniel T. wrote:
In article
<11**********************@f14g2000cwb.googlegroups .com>,
ro**********@gmail.com wrote:

The great thing about unsigned is if the value can't be negative
and you use signed then you always have to check it. Simply
defining the type as unsigned gets rid of all that as well as
documenting your domain. >> >> And the bad thing about unsigned
is that if code would otherwise make >> the value negative, you
can't check it. IE > > Surely overflow and underflow are a
problem
with both signed and unsigned?


These are often situations where you are unable to check validity
without domain specific knowledge - I don't see how signed unsigned
vary in that regard.


Because a signed negative value will be silently converted to a
positive unsigned value. I suppose this works both ways, though. I
can't prevent someone from passing a positive unsigned value to my
signed function, yielding the same problem in the mirror.


So the real problem is mixing signed and unsigned values. :-)

One solution, recommended elsewhere in this thread, is to just use one
kind. Probably signed then.
Bo Persson
Feb 22 '06 #26

P: n/a

"Ben Pope" <be***************@gmail.com> skrev i meddelandet
news:43**********************@taz.nntpserver.com.. .
Bob Hairgrove wrote:
On Wed, 22 Feb 2006 10:34:20 +0000, Ben Pope
<be***************@gmail.com> wrote:
Surely overflow and underflow are a problem with both signed and
unsigned?


They are a problem with signed (undefined or non-portable
behavior),
but behavior with unsigned is well-defined by the standard (values
wrap). There is never any true overflow with unsigned integral
values.


I guess that depends on your definition of overflow


In this context the difference is that with unsigned values you get a
known (but possibly useless) result. With signed artihmetic, you get
the dreaded "undefined behavior" - making your entire program formally
unusable.
Bo Persson
Feb 22 '06 #27

This discussion thread is closed

Replies have been disabled for this discussion.