473,698 Members | 1,976 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Style question: Use always signed integers or not?

I was once taught that if some integral value can never have negative
values, it's a good style to use an 'unsigned' type for that: It's
informative, self-documenting, and you are not wasting half of the value
range for values which you will never be using.

I agreed with this, and started to always use 'unsigned' whenever
negative values wouldn't make any sense. I did this for years.

However, I slowly changed my mind: Doing this often causes more
problems than it's worth. A good example:

If you have an image class, its width and height properties can
*never* get negative values. They will always be positive. So it makes
sense to use 'unsigned' for the width and height, doesn't it? What
problems could that ever create?

Well, assume that you are drawing images on screen, by pixel
coordinates, and these images can be partially (or completely) outside
the screen. For example, the left edge coordinate of the image to be
drawn might have a negative x value (for example drawing a 100x100 image
at coordinates <-20, 50>). Since the coordinates are signed and the
dimensions of the image are unsigned, this may cause signed-unsigned
mixup. For example this:

if(x - width/2 < 1) ...

where 'x' is a signed integer, gives *different* results depending on
whether 'width' is signed or unsigned, with certain values of those
variables (for example x=2 and width=10). The intention is to treat
'width' here as a signed value, but if it isn't, the comparison will
malfunction (without explicitly casting 'width' to a signed value). This
may well go completely unnoticed because compilers might not even give
any warning (for example gcc doesn't).

Thus at some point I started to *always* use signed integers unless
there was a very good reason not to. (Of course this sometimes causes
small annoyances because STL containers return an unsigned value for
their size() functions, but that's usually not a big problem.)

It would be interesting to hear other opinions on this subject.
Jun 27 '08 #1
39 2656
Juha Nieminen wrote:
I was once taught that if some integral value can never have negative
values, it's a good style to use an 'unsigned' type for that: It's
informative, self-documenting, and you are not wasting half of the value
range for values which you will never be using.

I agreed with this, and started to always use 'unsigned' whenever
negative values wouldn't make any sense. I did this for years.

However, I slowly changed my mind: Doing this often causes more
problems than it's worth. A good example:

If you have an image class, its width and height properties can
*never* get negative values. They will always be positive. So it makes
sense to use 'unsigned' for the width and height, doesn't it? What
problems could that ever create?

Well, assume that you are drawing images on screen, by pixel
coordinates, and these images can be partially (or completely) outside
the screen. For example, the left edge coordinate of the image to be
drawn might have a negative x value (for example drawing a 100x100 image
at coordinates <-20, 50>). Since the coordinates are signed and the
dimensions of the image are unsigned, this may cause signed-unsigned
mixup. For example this:

if(x - width/2 < 1) ...

where 'x' is a signed integer, gives *different* results depending on
whether 'width' is signed or unsigned, with certain values of those
variables (for example x=2 and width=10). The intention is to treat
'width' here as a signed value, but if it isn't, the comparison will
malfunction (without explicitly casting 'width' to a signed value). This
may well go completely unnoticed because compilers might not even give
any warning (for example gcc doesn't).

Thus at some point I started to *always* use signed integers unless
there was a very good reason not to. (Of course this sometimes causes
small annoyances because STL containers return an unsigned value for
their size() functions, but that's usually not a big problem.)

It would be interesting to hear other opinions on this subject.
Yes, I have had similar experiences / thoughts.

Some while back I thought it would be a good idea to use unsigned integers.
I don't think I read anywhere that this is good practice, and as a spare
time programmer I have never been on a C++ course; it just seemed 'obvious'
that using unsigned for values that can never be negative would be safer.

So I tried using unsigned integers in my simulation project. However I soon
started finding that I was getting compiler warnings about unsigned /
signed conversions. When I started trying to change more variables to
unsigned to stop the warnings, I just started getting more warnings.

I pretty soon abandoned the whole thing on the basis that it was more
trouble than it was worth (but also feeing slightly guilty).

I supposed that part of the problem might have been that I was trying to
retro-fit existing code, rather than coding from the outset to use
unsigned. However, the example given by Juha above makes me think that this
is not just a problem of retro-fitting. There seem to be scenarios where
using unsigned int is positively dangerous, particularly in scenarios where
the compiler doesn't generate a warning (and I've just confirmed on my own
gcc setup that there are such scenarios).

Rather than using unsigned, I use Assertions liberally, and having seen the
danger of signed/unsigned conversions, I think this is the right approach.

Chris Gordon-Smith
www.simsoup.info
Jun 27 '08 #2
On 2008-06-07 12:43, Juha Nieminen wrote:
I was once taught that if some integral value can never have negative
values, it's a good style to use an 'unsigned' type for that: It's
informative, self-documenting, and you are not wasting half of the value
range for values which you will never be using.

I agreed with this, and started to always use 'unsigned' whenever
negative values wouldn't make any sense. I did this for years.

However, I slowly changed my mind: Doing this often causes more
problems than it's worth. A good example:

If you have an image class, its width and height properties can
*never* get negative values. They will always be positive. So it makes
sense to use 'unsigned' for the width and height, doesn't it? What
problems could that ever create?

Well, assume that you are drawing images on screen, by pixel
coordinates, and these images can be partially (or completely) outside
the screen. For example, the left edge coordinate of the image to be
drawn might have a negative x value (for example drawing a 100x100 image
at coordinates <-20, 50>). Since the coordinates are signed and the
dimensions of the image are unsigned, this may cause signed-unsigned
mixup. For example this:

if(x - width/2 < 1) ...

where 'x' is a signed integer, gives *different* results depending on
whether 'width' is signed or unsigned, with certain values of those
variables (for example x=2 and width=10).
Wow, that was certainly an eye-opener. I had assumed that in this case
both values would be promoted to some larger type (signed long) which
could accurately represent both values (the signed and the unsigned int)
but apparently not.

This is a defect in the standard in my opinion since it allows the
correct action to be taken for types smaller than int:

#include <iostream>

int main()
{
unsigned short width = 10;
short x = 2;
std::cout << (x - width);
return 0;
}

--
Erik Wikström
Jun 27 '08 #3
Erik Wikström schrieb:
On 2008-06-07 12:43, Juha Nieminen wrote:
> I was once taught that if some integral value can never have negative
values, it's a good style to use an 'unsigned' type for that: It's
informative, self-documenting, and you are not wasting half of the value
range for values which you will never be using.

I agreed with this, and started to always use 'unsigned' whenever
negative values wouldn't make any sense. I did this for years.

However, I slowly changed my mind: Doing this often causes more
problems than it's worth. A good example:

If you have an image class, its width and height properties can
*never* get negative values. They will always be positive. So it makes
sense to use 'unsigned' for the width and height, doesn't it? What
problems could that ever create?

Well, assume that you are drawing images on screen, by pixel
coordinates, and these images can be partially (or completely) outside
the screen. For example, the left edge coordinate of the image to be
drawn might have a negative x value (for example drawing a 100x100 image
at coordinates <-20, 50>). Since the coordinates are signed and the
dimensions of the image are unsigned, this may cause signed-unsigned
mixup. For example this:

if(x - width/2 < 1) ...

where 'x' is a signed integer, gives *different* results depending on
whether 'width' is signed or unsigned, with certain values of those
variables (for example x=2 and width=10).

Wow, that was certainly an eye-opener. I had assumed that in this case
both values would be promoted to some larger type (signed long) which
could accurately represent both values (the signed and the unsigned int)
but apparently not.

This is a defect in the standard in my opinion since it allows the
correct action to be taken for types smaller than int:

#include <iostream>

int main()
{
unsigned short width = 10;
short x = 2;
std::cout << (x - width);
return 0;
}
is -8 (gcc 3.4.5/adam riese)...
Jun 27 '08 #4
On Jun 7, 7:43 am, Juha Nieminen <nos...@thanks. invalidwrote:
I was once taught that if some integral value can never have negative
values, it's a good style to use an 'unsigned' type for that: It's
informative, self-documenting, and you are not wasting half of the value
range for values which you will never be using.

I agreed with this, and started to always use 'unsigned' whenever
negative values wouldn't make any sense. I did this for years.

However, I slowly changed my mind: Doing this often causes more
problems than it's worth. A good example:

If you have an image class, its width and height properties can
*never* get negative values. They will always be positive. So it makes
sense to use 'unsigned' for the width and height, doesn't it? What
problems could that ever create?

Well, assume that you are drawing images on screen, by pixel
coordinates, and these images can be partially (or completely) outside
the screen. For example, the left edge coordinate of the image to be
drawn might have a negative x value (for example drawing a 100x100 image
at coordinates <-20, 50>). Since the coordinates are signed and the
dimensions of the image are unsigned, this may cause signed-unsigned
mixup. For example this:

if(x - width/2 < 1) ...

where 'x' is a signed integer, gives *different* results depending on
whether 'width' is signed or unsigned, with certain values of those
variables (for example x=2 and width=10). The intention is to treat
'width' here as a signed value, but if it isn't, the comparison will
malfunction (without explicitly casting 'width' to a signed value). This
may well go completely unnoticed because compilers might not even give
any warning (for example gcc doesn't).

Thus at some point I started to *always* use signed integers unless
there was a very good reason not to. (Of course this sometimes causes
small annoyances because STL containers return an unsigned value for
their size() functions, but that's usually not a big problem.)

It would be interesting to hear other opinions on this subject.
It's a good moment for re-read Stroustrups The C++ Programming
Language
He talks about usual conversions un binary operators.
Your example: if(x - width/2 < 1) ...
considering x as int and width as unsigned, should return a unsigned
value.
There are a lot more of basic conversion rules, but i think it fits
here.
I've assumed (until today) the compiler autocast width to signed
before makes the comparison, but it is not true.
About your question, I still think that if the value will never have a
negative value, it should be unsigned, because of the reasons you had
told. The example of the properties of an image is valid, for the
first argument, width and height properties will allways be non
negative, but another thing is to calculate where you're going to draw
them. Where your are going to draw is a coordinate, and they certainly
can be negative, so they have the be signed values. But we where
mixing the concept of a coordinate with a width and height. Booth are
related at drawing time, but not the same thing.

Darío
Jun 27 '08 #5
On Jun 7, 11:43*am, Juha Nieminen <nos...@thanks. invalidwrote:
* If you have an image class, its width and height properties can
*never* get negative values. They will always be positive. So it makes
sense to use 'unsigned' for the width and height, doesn't it? What
problems could that ever create?

* Well, assume that you are drawing images on screen, by pixel
coordinates, and these images can be partially (or completely) outside
the screen. For example, the left edge coordinate of the image to be
drawn might have a negative x value (for example drawing a 100x100 image
at coordinates <-20, 50>).

I agree that this is a case where you'd consider using signed integer
types, but I'm still a stedfast unsigned man. My major peeve with
signed integer types is their undefined behaviour upon overflow.

(Of course the less pretty solution is to use casts in your code)
Jun 27 '08 #6
Tomás Ó hÉilidhe <to*@lavabit.co mkirjutas:
types, but I'm still a stedfast unsigned man. My major peeve with
signed integer types is their undefined behaviour upon overflow.
You mean that you are fond of the following code having no undefined
behavior? Sorry, I have not encountered a need for this kind of defined
behavior!

#include <iostream>

int main() {
unsigned int a = 2150000000u;
unsigned int b = 2160000000u;
unsigned int c = (a+b)/2;

std::cout << "a=" << a << "\nb=" << b <<
"\nand their average\nc=" << c << "\n";
}

Output (32-bit unsigned ints):

a=2150000000
b=2160000000
and their average
c=7516352

The unsigned integers in C/C++ are very specific cyclic types with
strange overflow and wrapping rules. IMHO, these should be used primarily
in some very specific algorithms needing such cyclic types.

Regards
Paavo
Jun 27 '08 #7
Juha Nieminen <no****@thanks. invalidwrote:
I was once taught that if some integral value can never have negative
values, it's a good style to use an 'unsigned' type for that: It's
informative, self-documenting, and you are not wasting half of the value
range for values which you will never be using.

I agreed with this, and started to always use 'unsigned' whenever
negative values wouldn't make any sense. I did this for years.

However, I slowly changed my mind: Doing this often causes more
problems than it's worth. A good example:

If you have an image class, its width and height properties can
*never* get negative values. They will always be positive. So it makes
sense to use 'unsigned' for the width and height, doesn't it? What
problems could that ever create?

Well, assume that you are drawing images on screen, by pixel
coordinates, and these images can be partially (or completely) outside
the screen. For example, the left edge coordinate of the image to be
drawn might have a negative x value (for example drawing a 100x100 image
at coordinates <-20, 50>). Since the coordinates are signed and the
dimensions of the image are unsigned, this may cause signed-unsigned
mixup. For example this:

if(x - width/2 < 1) ...

where 'x' is a signed integer, gives *different* results depending on
whether 'width' is signed or unsigned, with certain values of those
variables (for example x=2 and width=10). The intention is to treat
'width' here as a signed value, but if it isn't, the comparison will
malfunction (without explicitly casting 'width' to a signed value). This
may well go completely unnoticed because compilers might not even give
any warning (for example gcc doesn't).

Thus at some point I started to *always* use signed integers unless
there was a very good reason not to. (Of course this sometimes causes
small annoyances because STL containers return an unsigned value for
their size() functions, but that's usually not a big problem.)

It would be interesting to hear other opinions on this subject.
From Stroustrup:

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.

I especially like this quote from Gavin Deane:

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.
Jun 27 '08 #8
On 2008-06-07 16:47, Chris Forone wrote:
Erik Wikström schrieb:
>On 2008-06-07 12:43, Juha Nieminen wrote:
>> I was once taught that if some integral value can never have negative
values, it's a good style to use an 'unsigned' type for that: It's
informative , self-documenting, and you are not wasting half of the value
range for values which you will never be using.

I agreed with this, and started to always use 'unsigned' whenever
negative values wouldn't make any sense. I did this for years.

However, I slowly changed my mind: Doing this often causes more
problems than it's worth. A good example:

If you have an image class, its width and height properties can
*never* get negative values. They will always be positive. So it makes
sense to use 'unsigned' for the width and height, doesn't it? What
problems could that ever create?

Well, assume that you are drawing images on screen, by pixel
coordinates , and these images can be partially (or completely) outside
the screen. For example, the left edge coordinate of the image to be
drawn might have a negative x value (for example drawing a 100x100 image
at coordinates <-20, 50>). Since the coordinates are signed and the
dimensions of the image are unsigned, this may cause signed-unsigned
mixup. For example this:

if(x - width/2 < 1) ...

where 'x' is a signed integer, gives *different* results depending on
whether 'width' is signed or unsigned, with certain values of those
variables (for example x=2 and width=10).

Wow, that was certainly an eye-opener. I had assumed that in this case
both values would be promoted to some larger type (signed long) which
could accurately represent both values (the signed and the unsigned int)
but apparently not.

This is a defect in the standard in my opinion since it allows the
correct action to be taken for types smaller than int:

#include <iostream>

int main()
{
unsigned short width = 10;
short x = 2;
std::cout << (x - width);
return 0;
}

is -8 (gcc 3.4.5/adam riese)...
Exactly, but if you use int instead of short you get 4294967288, because
the unsigned int is not promoted to a signed long.

--
Erik Wikström
Jun 27 '08 #9
Paavo Helde wrote:
Daniel Pitts <ne************ ******@virtuali nfinity.netkirj utas:
>Paavo Helde wrote:
>>Tomás Ó hÉilidhe <to*@lavabit.co mkirjutas:

types, but I'm still a stedfast unsigned man. My major peeve with
signed integer types is their undefined behaviour upon overflow.

You mean that you are fond of the following code having no undefined
behavior? Sorry, I have not encountered a need for this kind of
defined behavior!

#include <iostream>

int main() {
unsigned int a = 2150000000u;
unsigned int b = 2160000000u;
unsigned int c = (a+b)/2;

std::cout << "a=" << a << "\nb=" << b <<
"\nand their average\nc=" << c << "\n";
}

Output (32-bit unsigned ints):

a=215000000 0
b=216000000 0
and their average
c=7516352

The unsigned integers in C/C++ are very specific cyclic types with
strange overflow and wrapping rules. IMHO, these should be used
primarily in some very specific algorithms needing such cyclic types.

Regards
Paavo
I don't have a copy of the standard, but does the standard actually
define unsigned integral types as having that overflow behavior? Or is
that just the "most common case"?

I'm not questioning to make a point, I really would like to know the
answer.

Thanks,
Daniel.

AFAIK the unsigned arithmetics is specified exactly by the standard. This
means for example that a debug implementation cannot detect and assert the
overflow, but has to produce the wrapped result instead:

<quote>

3.9.1/4:

Unsigned integers, declared unsigned, shall obey the laws of arithmetic
modulo 2^n where n is the number of bits in the value representation of
that particular size of integer.

Footnote: This implies that unsigned arithmetic does not overflow because
a result that cannot be represented by the resulting unsigned integer type
is reduced modulo the number that is one greater than the largest value
that can be represented by the resulting unsigned integer
type.

</quote>

In the above example one should also consider the effects of integral
promotion - the internal calculations are done in unsigned int, which
means that a similar example with unsigned shorts or chars would appear to
work correctly. However, I am not sure where the standard says that
3.9.1/4 can be violated by promoting the operands to a larger type.
[5.9]
By considering 3.9.1/4 only it seems that one should have:

unsigned char a=128u, b=128u, c=(a+b)/2; assert(c==0);

Fortunately, this is not the case with my compilers ;-)
I am not so sure whether we are really fortunate to have integral
promotions.
Best

Kai-Uwe Bux
Jun 27 '08 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

21
3104
by: nephish | last post by:
i have an interesting project at work going on. here is the challenge. i am using the serial module to read data from a serial input. it comes in as a hex. i need to make it a binary and compare it bit by bit to another byte. They have some weird way they set this up that i have to compare these things with AND. in other words, if bit 1 is 1 AND bit 1 is 1 then the real value is 1... long story short. is there a good way to compare...
54
2912
by: Sander | last post by:
1. I was having a discussion with somebody and I think it's just religious. We are developing some software and he was looking through my code. I use if (pointer) to test a pointer for NULL. He says it must be if (p!=NULL). The arguments are that it's more readable and that if (p) is not portable. I said the first is a style issue and that I think if(p) is more readable and that the second is plain wrong. So, is he right about the...
18
3036
by: David Buchan | last post by:
Hi guys, This may be a dumb question; I'm just getting into C language here. I wrote a program to unpack a binary file and write out the contents to a new file as a list of unsigned integers. It works on an IBM mainframe under AIX with GCC, but has trouble on Intel with GCC (DJGPP). I think it's an endian problem. The trouble is, although most values in the extracted list are correct,
19
1744
by: Ramesh Tharma | last post by:
Hi, Is any one knows what's wrong with the following code, I was told that it will compile and run but it will crash for some values. Assume that variables are initilized. char* c; long* lg;
11
2668
by: Frederick Gotham | last post by:
I'd like to discuss the use of signed integers types where unsigned integers types would suffice. A common example would be: #include <cassert> #include <cstddef> int CountOccurrences(unsigned char const val, unsigned char const p,
70
2088
by: jan.chludzinski | last post by:
Are the variables on the righthand side of an assignment statement treated strictly as values? That is, if in assigning to an "unsigned int" I shift a "unsigned char" 24 places to the left, can I trust that the compiler will use temp storage sufficient to hold the "unsigned int" and NOT result in an overflow (because I shifted an "unsigned char" 24 places)? Using gcc I tried the code below: #include <stdio.h>
37
1978
by: Richard Heathfield | last post by:
candide said: They aren't. An array is an array. An address is a pointer value. These are not the same thing. If you mean that &array and &array are the same, they aren't. They have different types. If you try to take the value of an array, what you actually get is the value of a pointer to the first member of the array. That doesn't mean
22
2763
by: Bill Reid | last post by:
I just noticed that my "improved" version of sscanf() doesn't assign floating point numbers properly if the variable assigned to is declared as a "float" rather than a "double". (This never cropped up before, since I rarely use "float"s for anything, and hardly ever use the function for floating-point numbers in the first place; I just was messing around testing it for all cases and noticed a problem.) Anyway, it is declared and I...
40
2467
by: Phlip | last post by:
Scott Lurndal wrote: Would it also cause a problem if your file descriptors go "around the horn", and exceed some platform-specific limit, such as 0x80000000? They would "go negative" when expressed as signed integers... Does some relatively standard .h file define a good constant there?
0
9156
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
9021
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
0
7712
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
1
6518
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
5860
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
4361
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
0
4614
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
2
2323
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
3
1998
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.