473,722 Members | 2,468 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
39 2662
On 2008-06-08 12:16, Juha Nieminen wrote:
Erik Wikström wrote:
>Exactly, but if you use int instead of short you get 4294967288, because
the unsigned int is not promoted to a signed long.

What would be the difference between promoting an unsigned int to a
signed int vs. to a signed long in an architecture where int and long
are the same thing (ie. basically all 32-bit systems)?
None, but then the limitation would (partially) be in the platform and
not in the language. What I complain about is the fact that integer
promotion is specified for types "smaller" than int, but not for
"larger" types. Considering that many desktop machines now easily can
handle types larger than int (which is often 32 bits even on 64-bit
machines) this seems a bit short-sighted to me. I can see no reason to
allow integer promotion for all integer types.

--
Erik Wikström
Jun 27 '08 #21
In article <g2**********@a ioe.org>, jk********@gmx. net says...

[ ... ]
a) There is <limits>, which will tell you portably the bounds of built-in
types.
Yes, but 1) it doesn't guarantee that the size you need will be present,
and 2) even if the size you need is present, it may not be represented
completely accurately.

For example, on one (admittedly old) compiler, <limits.hsaid that that
SCHAR_MIN was -127 -- but this was on a twos-complement machine where
the limit was really -128. At the time the committee discussed it, and
at least from what I heard, agreed that this didn't fit what they
wanted, but DID conform with the requirements of the standard.

Even when/if <limits.hdoes contain the correct data, and the right
size is present, you can end up with a rather clumsy ladder to get the
right results.

#if (unsigned char is the right size)
typedef unisgned char typeIneed;
#elif (unsigned short is the right size)
typedef unsigned short typeIneed;
#elif (unsigned int is the right size)
typedef unsigned int typeIneed;
#elif (unsigned long is the right size)
typedef unsigned long typeIneed;
#else
#error correct size not present?
#endif

Fortunately, you most often care about sizes like 16 and 32 bits. C99
and C++ 0x allow you to get sizes like them much more easily, using
uintXX_t.

--
Later,
Jerry.

The universe is a figment of its own imagination.
Jun 27 '08 #22
Jerry Coffin wrote:
In article <g2**********@a ioe.org>, jk********@gmx. net says...

[ ... ]
Let's restore some important context: You wrote:
In article <Xn************ *************@2 16.196.97.131>, no****@ebi.ee
says...

[ ... ]
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:

Unsigned arithmetic is defined in all but one respect: the sizes of the
integer types. IOW, you know how overflow is handled when it does
happen, but you don't (portably) know when it'll happen.
Note the claim that one cannot know when overflow will happen.

To _that_, I answered:
>a) There is <limits>, which will tell you portably the bounds of built-in
types.
And now, you say:
Yes, but 1) it doesn't guarantee that the size you need will be present,
which is completely unrelated to the question whether you can portably
detect overflow, and:
and 2) even if the size you need is present, it may not be represented
completely accurately.
which is just FUD.
For example, on one (admittedly old) compiler, <limits.hsaid that that
SCHAR_MIN was -127 -- but this was on a twos-complement machine where
the limit was really -128. At the time the committee discussed it, and
at least from what I heard, agreed that this didn't fit what they
wanted, but DID conform with the requirements of the standard.
Yes. And on that compiler, SCHAR_MIN _was_ -127. That _means_ that the
implementation made no guarantees about behavior when computations
reach -128 even though experiments or documentation about the computer
architecture suggest you could there. The point is that SCHAR_MIN _defines_
what counts as overflow for the signed char type.

In short: contrary to your claim, you can portably detect overflow (and it
is particularly easy for unsigned types, where issues like the one with
SCHAR_MIN cannot happen).
Best

Kai-Uwe Bux
Jun 27 '08 #23
In article <g2**********@a ioe.org>, jk********@gmx. net says...

[ ... ]
For example, on one (admittedly old) compiler, <limits.hsaid that that
SCHAR_MIN was -127 -- but this was on a twos-complement machine where
the limit was really -128. At the time the committee discussed it, and
at least from what I heard, agreed that this didn't fit what they
wanted, but DID conform with the requirements of the standard.

Yes. And on that compiler, SCHAR_MIN _was_ -127. That _means_ that the
implementation made no guarantees about behavior when computations
reach -128 even though experiments or documentation about the computer
architecture suggest you could there. The point is that SCHAR_MIN _defines_
what counts as overflow for the signed char type.
The problem is, that the wording for that part of the standard has
remained essentially the same, and still doesn't require that the values
in limits.h (or equivalents inside of namespace std) be truly accurate
in telling you the limits of the implementation. The implementation
clearly DOES have to provide AT LEAST the range specified, but there is
_nothing_ to prevent it from exceeding that range.
In short: contrary to your claim, you can portably detect overflow (and it
is particularly easy for unsigned types, where issues like the one with
SCHAR_MIN cannot happen).
Yes, it CAN happen for unsigned types. An implementation could (for
example) supply 32-it integers, but claim that UINT_MAX was precisely 4
billion. The unsigned integer in question would NOT wrap at precisely 4
billion (and, in fact, an implementation that did would not conform).

Contrary to YOUR claim, I did NOT ever claim that you can't portably
detect overflow. What I said was:
Yes, but 1) it doesn't guarantee that the size you need will be present,
and 2) even if the size you need is present, it may not be represented
completely accurately.
and:
Even when/if <limits.hdoes contain the correct data, and the right
size is present, you can end up with a rather clumsy ladder to get the
right results.
The fact is that I neither said nor implied that you could not portably
detect "overflow" (i.e. wraparound on an unsigned type).

What I said, and I maintain that it's true (and you've yet to show any
evidence of any sort to the contrary) was that 1) the information in
limits.h can be misleading, and 2) when/if you want wraparound at a
specific size, you're not guaranteed that such a size will exist, and 3)
even when/if it does exist, actually finding and using it can be clumsy.

--
Later,
Jerry.

The universe is a figment of its own imagination.
Jun 27 '08 #24
[snip]

Jerry Coffin wrote:
The fact is that I neither said nor implied that you could not portably
detect "overflow" (i.e. wraparound on an unsigned type).
Really? This is from uptrhead:

Jerry Coffin wrote:
In article <Xn************ *************@2 16.196.97.131>, no****@ebi.ee
says...

[ ... ]
>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:

Unsigned arithmetic is defined in all but one respect: the sizes of the
integer types. IOW, you know how overflow is handled when it does
happen, but you don't (portably) know when it'll happen.
Now, if somebody impersonated you, I apologize.

Whoever made the statement

"IOW, you know how overflow is handled when it does happen, but you don't
(portably) know when it'll happen."

was mistaken. This is the statement I responded to. Snipping it away over
and over again will not change that.
Best

Kai-Uwe Bux
Jun 27 '08 #25
In article <g2**********@a ioe.org>, jk********@gmx. net says...

[ ... ]
Whoever made the statement

"IOW, you know how overflow is handled when it does happen, but you don't
(portably) know when it'll happen."

was mistaken. This is the statement I responded to. Snipping it away over
and over again will not change that.
It is not what you responded to, and it IS correct. You do NOT know (a
priori) exactly when it'll happen. Nothing in limits.h changes that. I'd
quote the standard, but the problem is that this is simply a situation
in which there's nothing in the standard to quote. If you want to claim
that the number given as (for example) UINT_MAX in limits.h precisely
reflects when arithmetic with an unisgned integer will wrap around, you
have two choices: quote something from the standard that says so, or
else admit that it doesn't exist (or, if course, continue as you are
now, making wild, unsupported accusations!)

--
Later,
Jerry.

The universe is a figment of its own imagination.
Jun 27 '08 #26
Jerry Coffin wrote:
In article <g2**********@a ioe.org>, jk********@gmx. net says...

[ ... ]
>Whoever made the statement

"IOW, you know how overflow is handled when it does happen, but you
don't (portably) know when it'll happen."

was mistaken. This is the statement I responded to. Snipping it away over
and over again will not change that.

It is not what you responded to,
The record clearly shows that this is precisely the statement I responded
to. I would quote my response posting in full, but let me just paste a link
to Google instead (apologies: I had to break the line to please my
newsreader):

http://groups.google.com/group/comp....ee/browse_frm/
thread/52f4c25b71dee3a 5/8911caf6152e4b1 e?rnum=11
&_done=%2Fgroup %2Fcomp.lang.c% 2B%2B%2Fbrowse_ frm%2Fthread
%2F52f4c25b71de e3a5%3F#doc_5c3 e4897ec30f171

If there is any meaning to using bottom-posting as opposed to top-posting,
it should be clear that I responded to no other claim than the above.

and it IS correct. You do NOT know (a
priori) exactly when it'll happen. Nothing in limits.h changes that.
Nothing in <limitsis needed for unsigned types. The standard guarantees
that

(unsigned int)(-1)

is 2^N-1 where N is the bitlength of unsigned int [4.7/2]. The corresponding
statements for other unsigned types are true, too.
I'd
quote the standard, but the problem is that this is simply a situation
in which there's nothing in the standard to quote. If you want to claim
that the number given as (for example) UINT_MAX in limits.h precisely
reflects when arithmetic with an unisgned integer will wrap around, you
have two choices:
Formally, I did not claim that that numeric_limits< unsigned int>::max()
gives the same value as (unsigned int)(-1). However, you are correct that I
mentioned <limitsin response to the above, possibly creating the
impression that this was the case.

On the other hand, The main part of my response demonstrated a check for
overflow that does not rely on <limits>.

quote something from the standard that says so, or
else admit that it doesn't exist (or, if course, continue as you are
now, making wild, unsupported accusations!)
I don't make unsupported accusations. I just restore context by quoting.
Also, I disagree with the statement that we cannot know when overflow will
happen for unsigned types. If your case for that statement relies on
<limitsbeing underspecified, I think the above observation from [4.7/2]
should clear things up.
Best

Kai-Uwe Bux
Jun 27 '08 #27
In article <g2**********@a ioe.org>, jk********@gmx. net says...

[ ... ]
and it IS correct. You do NOT know (a
priori) exactly when it'll happen. Nothing in limits.h changes that.

Nothing in <limitsis needed for unsigned types. The standard guarantees
that

(unsigned int)(-1)

is 2^N-1 where N is the bitlength of unsigned int [4.7/2]. The corresponding
statements for other unsigned types are true, too.
The point of my statement was that you don't know N ahead of time.
Nothing you've said changes that.

[ ... ]
On the other hand, The main part of my response demonstrated a check for
overflow that does not rely on <limits>.
Yes, but it doesn't tell you ahead of time, when it'll happen, because
you don't know what the size of any specific integer type will be.
quote something from the standard that says so, or
else admit that it doesn't exist (or, if course, continue as you are
now, making wild, unsupported accusations!)

I don't make unsupported accusations. I just restore context by quoting.
You did make unsupported accusations, and you still haven't quoted a
single thing from the standard to support them. You won't either,
because they AREN'T there.
Also, I disagree with the statement that we cannot know when overflow will
happen for unsigned types. If your case for that statement relies on
<limitsbeing underspecified, I think the above observation from [4.7/2]
should clear things up.
Then you haven't got a clue of what you're talking about! The quote
above does NOT tell you the size of any unsigned integer type, which is
exactly what you need before you know when wraparound will happen.

--
Later,
Jerry.

The universe is a figment of its own imagination.
Jun 27 '08 #28
Jerry Coffin wrote:
In article <g2**********@a ioe.org>, jk********@gmx. net says...

[ ... ]
For example, on one (admittedly old) compiler, <limits.hsaid that
that SCHAR_MIN was -127 -- but this was on a twos-complement machine
where the limit was really -128. At the time the committee discussed
it, and at least from what I heard, agreed that this didn't fit what
they wanted, but DID conform with the requirements of the standard.

Yes. And on that compiler, SCHAR_MIN _was_ -127. That _means_ that the
implementati on made no guarantees about behavior when computations
reach -128 even though experiments or documentation about the computer
architecture suggest you could there. The point is that SCHAR_MIN
_defines_ what counts as overflow for the signed char type.

The problem is, that the wording for that part of the standard has
remained essentially the same, and still doesn't require that the values
in limits.h (or equivalents inside of namespace std) be truly accurate
in telling you the limits of the implementation. The implementation
clearly DOES have to provide AT LEAST the range specified, but there is
_nothing_ to prevent it from exceeding that range.
>In short: contrary to your claim, you can portably detect overflow (and
it is particularly easy for unsigned types, where issues like the one
with SCHAR_MIN cannot happen).

Yes, it CAN happen for unsigned types. An implementation could (for
example) supply 32-it integers, but claim that UINT_MAX was precisely 4
billion.
Are you sure this can happen on a standard conforming implementation?

In [18.2.1.2/4], the standard describes

numeric_limits< T>::max() throw();

as returning the "maximum finite value". In a footnote, it also requires
that UINT_MAX agrees with numeric_limits< unsigned int>::max(). In the
suggested implementation, 4.000.000.001 would be a valid unsinged int
bigger than numeric_limits< unsigned int>::max(), which contradicts the
standard. (Admittedly, I do not know whether footnotes like that are
normative. But, in any case, numeric_limits< T>::max() should give you the
maximum finite value portably according to the standard.
The unsigned integer in question would NOT wrap at precisely 4
billion (and, in fact, an implementation that did would not conform).
Agreed, but I think the implementation would be non-conforming anyway.
[snip]
Best

Kai-Uwe Bux
Jun 27 '08 #29
Jerry Coffin wrote:
In article <g2**********@a ioe.org>, jk********@gmx. net says...

[ ... ]
and it IS correct. You do NOT know (a
priori) exactly when it'll happen. Nothing in limits.h changes that.

Nothing in <limitsis needed for unsigned types. The standard guarantees
that

(unsigned int)(-1)

is 2^N-1 where N is the bitlength of unsigned int [4.7/2]. The
correspondin g statements for other unsigned types are true, too.

The point of my statement was that you don't know N ahead of time.
Nothing you've said changes that.
I am utterly confused now. Clearly we have different understandings of what
it means to "know (a priory) exactly when it [overflow] will happen.".

I took your words to mean that I cannot determine at compile time the upper
bound for an unsigned type. The word "portably" in your phrase:

IOW, you know how overflow is handled when it does happen, but you don't
(portably) know when it'll happen.

seemed to indicate that, and your follow up remarks on the unreliability of
limits.h strengthened that interpretation in my mind (as I got the
impression that you maintained that the portability issue arose from
possible inaccurate bounds in <limits>).

Now, it appears that you had something different in mind. I am somewhat lost
at seeing what it might be.

[ ... ]
>On the other hand, The main part of my response demonstrated a check for
overflow that does not rely on <limits>.

Yes, but it doesn't tell you ahead of time, when it'll happen, because
you don't know what the size of any specific integer type will be.
quote something from the standard that says so, or
else admit that it doesn't exist (or, if course, continue as you are
now, making wild, unsupported accusations!)

I don't make unsupported accusations. I just restore context by quoting.

You did make unsupported accusations,
I maintain that

(a) all my "accusation s" where supported (they were all of the form "you
claimed ...", "you snipped ..." or some such thing, and all of them were
supported by quotes) and

(b) all my unsupported claims (of which I may have made a few) do not
qualify as accusations (since they are not criticisms targeted toward
anybody).
If you felt offended by any of my remarks, I am sorry.

and you still haven't quoted a single thing from the standard to support
them. You won't either, because they AREN'T there.
How and why would I support a claim of the form "you claimed ..." by a quote
from the standard?

>Also, I disagree with the statement that we cannot know when overflow
will happen for unsigned types. If your case for that statement relies on
<limitsbeing underspecified, I think the above observation from [4.7/2]
should clear things up.

Then you haven't got a clue of what you're talking about! The quote
above does NOT tell you the size of any unsigned integer type, which is
exactly what you need before you know when wraparound will happen.
I am pretty certain tha I know what I am talking about. It might however be
something that you were not talking about and I may have misinterpreted
your claim(s).

The above quote allows you to portably(!) determine the size of any unsigned
integer type at compile time. If that is not what you mean by "(portably)
know when [overflow will happen]", I was just misunderstandin g you.
Best

Kai-Uwe Bux
Jun 27 '08 #30

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

Similar topics

21
3113
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
2920
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
3040
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
1748
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
2671
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
2094
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
1987
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
2766
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
2481
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
8867
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
9386
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...
1
9158
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
9090
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
1
6685
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
4503
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...
1
3208
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
2
2606
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
3
2148
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.