By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
457,723 Members | 1,147 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 457,723 IT Pros & Developers. It's quick & easy.

Standard integer types vs <stdint.h> types

P: n/a
char and unsigned char have specific purposes: char is useful for
representing characters of the basic execution character set and
unsigned char is useful for representing the values of individual
bytes. The remainder of the standard integer types are general
purpose. Their only requirement is to satisfy a minimum range of
values, and also int "has the natural size suggested by the
architecture of the execution environment". What are the reasons for
using these types instead of the [u]int_fastN_t types of <stdint.h>?

If I want just a signed integer with at least 16 width, then why
choose int instead of int_fast16_t? int_fast16_t is the "fastest"
signed integer type that has at least 16 width, while int is simply a
signed integer type that has at least 16 width. It seems that choosing
int_fast16_t is at least as good as choosing int. This argument can be
made for N=8,16,32,64, and for the corresponding unsigned types.
<stdint.halso offers [u]int_leastN_t types, which are useful when
keeping a small storage size is the greatest concern.

The only benefit of using the standard integer types I can see is that
their ranges may expand as the C standard progresses, so code that
uses them might stay useful over time. For example fseek of <stdio.h>
uses a long for its offset parameter, so if the range of long grows
then fseek will automatically offer a wider range of offsets.

It's also interesting to note (or maybe not) that in the Windows
world, the idea of long being general purpose has somewhat been
destroyed and long has become a type that must have exactly 32 bits.
Jan 18 '08 #1
Share this Question
Share on Google+
130 Replies


P: n/a
<eu*****@gmail.comwrote in message
char and unsigned char have specific purposes: char is useful for
representing characters of the basic execution character set and
unsigned char is useful for representing the values of individual
bytes. The remainder of the standard integer types are general
purpose. Their only requirement is to satisfy a minimum range of
values, and also int "has the natural size suggested by the
architecture of the execution environment". What are the reasons for
using these types instead of the [u]int_fastN_t types of <stdint.h>?

If I want just a signed integer with at least 16 width, then why
choose int instead of int_fast16_t? int_fast16_t is the "fastest"
signed integer type that has at least 16 width, while int is simply a
signed integer type that has at least 16 width. It seems that choosing
int_fast16_t is at least as good as choosing int. This argument can be
made for N=8,16,32,64, and for the corresponding unsigned types.
<stdint.halso offers [u]int_leastN_t types, which are useful when
keeping a small storage size is the greatest concern.

The only benefit of using the standard integer types I can see is that
their ranges may expand as the C standard progresses, so code that
uses them might stay useful over time. For example fseek of <stdio.h>
uses a long for its offset parameter, so if the range of long grows
then fseek will automatically offer a wider range of offsets.

It's also interesting to note (or maybe not) that in the Windows
world, the idea of long being general purpose has somewhat been
destroyed and long has become a type that must have exactly 32 bits.
Yes, we're rapidly going down the path of destroying the C basic integer
types.

Once you start inventing types like int_fast16_t people will use them, and
the language becomes more and more difficult to read.

My own view is that you should be able to stick to char for characters and
int for integers, in almost every situation. However this is only tenable if
you can use int as both an arbitrary array index and a fast type.

--
Free games and programming goodies.
http://www.personal.leeds.ac.uk/~bgy1mm
Jan 18 '08 #2

P: n/a
Malcolm McLean wrote, On 18/01/08 09:09:
<eu*****@gmail.comwrote in message
>char and unsigned char have specific purposes: char is useful for
representing characters of the basic execution character set and
unsigned char is useful for representing the values of individual
bytes.
Yes. Also pointer to char is the type normally taken by "string"
functions including (but not limited to) those in the standard library.
>The remainder of the standard integer types are general
purpose. Their only requirement is to satisfy a minimum range of
values, and also int "has the natural size suggested by the
architecture of the execution environment".
Yes.
>What are the reasons for
using these types instead of the [u]int_fastN_t types of <stdint.h>?
Well, stdint.h was only introduced in the 1999 standard, a standard that
is not fully implemented by many compilers and not at all by at least
one major player.
>If I want just a signed integer with at least 16 width, then why
choose int instead of int_fast16_t? int_fast16_t is the "fastest"
signed integer type that has at least 16 width, while int is simply a
signed integer type that has at least 16 width. It seems that choosing
int_fast16_t is at least as good as choosing int. This argument can be
made for N=8,16,32,64, and for the corresponding unsigned types.
Yes, this is true, and an excellent reason for using them. It does limit
portability to implementations that do not support this part of C99,
however it is always possible to write your own version of stdint.h for
those systems.
><stdint.halso offers [u]int_leastN_t types, which are useful when
keeping a small storage size is the greatest concern.
Yes. Also due to the possibly smaller size they can be *faster* for some
purposes. For example if the smaller size means everything is kept in
cache instead of having to be fetched.
>The only benefit of using the standard integer types I can see is that
their ranges may expand as the C standard progresses, so code that
uses them might stay useful over time.
Yes, that is a potential advantage.
>For example fseek of <stdio.h>
uses a long for its offset parameter, so if the range of long grows
then fseek will automatically offer a wider range of offsets.
There is an argument that fseek should have used another type...

Of course, that is why there is fsetpos.
>It's also interesting to note (or maybe not) that in the Windows
world, the idea of long being general purpose has somewhat been
destroyed and long has become a type that must have exactly 32 bits.
Yes, and it is not entirely the fault of MS. It is the programmers who
assumed that it would always be exactly 32 bits and/or assumed it would
always be the same size as int. Not breaking such 3rd party code, as I
understand it, was the reason for MS keeping long as 32 bits on Win64.
Yes, we're rapidly going down the path of destroying the C basic integer
types.
Note that this is an opinion that seems to be almost unique to Malcolm.
A lot of what Malcolm disagrees with was part of the original standard
published in 1989 so he has a very strange idea of "rapidly".

Note that some others think the fixed width types are a mistake,
although some of us disagree, there being arguments on both side. More
people (I think) would have liked things like int32_t being the fast
types and having int_exact or int_fixed for the optional fixed sized types.
Once you start inventing types like int_fast16_t people will use them,
and the language becomes more and more difficult to read.
In *your* opinion.
My own view is that you should be able to stick to char for characters
and int for integers, in almost every situation. However this is only
tenable if you can use int as both an arbitrary array index and a fast
type.
Which is not its purpose and does not agree with the way modern
processors work since often a 32 bit integer will be faster than a 64
bit integer (even on 64 bit hardware) yet you need a 64 bit integer for
an arbitrary index. Similar things were true for eariler HW in terms of
16/32 bits. So Malcolm's view is that C has to meet two contradictory
requirements at the same time.
--
Flash Gordon
Jan 18 '08 #3

P: n/a

"Malcolm McLean" <re*******@btinternet.comwrote in message
news:pM******************************@bt.com...
<eu*****@gmail.comwrote in message
....
>It's also interesting to note (or maybe not) that in the Windows
world, the idea of long being general purpose has somewhat been
destroyed and long has become a type that must have exactly 32 bits.
Yes, we're rapidly going down the path of destroying the C basic integer
types.

Once you start inventing types like int_fast16_t people will use them, and
the language becomes more and more difficult to read.
>
My own view is that you should be able to stick to char for characters and
int for integers, in almost every situation. However this is only tenable
if you can use int as both an arbitrary array index and a fast type.
My own view is the opposite. How can one program without knowing the bitsize
of one's datatypes? But I've probably spent too many years low-level
programming.

I gave one example in c.l.c recently of a long int datatype that was either
32 or 64-bits depending on compiler -- on the same processor. So if you port
a supposedly portable program from one compiler to another, it could run
much slower (or faster).

Anyway for interfacing with other (binary) software, the exact sizes of
datatypes becomes important. Or (in my case) trying to interface from
another language to C.

--
Bart


Jan 18 '08 #4

P: n/a
Flash Gordon said:
Malcolm McLean wrote, On 18/01/08 09:09:
<snip>
>Yes, we're rapidly going down the path of destroying the C basic integer
types.

Note that this is an opinion that seems to be almost unique to Malcolm.
A lot of what Malcolm disagrees with was part of the original standard
published in 1989 so he has a very strange idea of "rapidly".
Here at least, I can agree with you.
Note that some others think the fixed width types are a mistake,
although some of us disagree, there being arguments on both side. More
people (I think) would have liked things like int32_t being the fast
types and having int_exact or int_fixed for the optional fixed sized
types.
I would rather not have seen these types at all, since they seem to me to
enshrine poor practice. But I recognise that there are some spheres of
programming in which they could prove useful.
>Once you start inventing types like int_fast16_t people will use them,
and the language becomes more and more difficult to read.

In *your* opinion.
I think he has a point. At the very least, it becomes *uglier* to read. C
as it stands, if well-written, is at least a relatively elegant language,
not just technically and syntactically but also visually. All these
stretched-out underscore-infested type names will be a real nuisance when
scanning quickly through unfamiliar code.

<snip>

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
Jan 18 '08 #5

P: n/a
Bart C said:
How can one program without knowing the bitsize of one's datatypes?
We know the minimum value range of our data types - why would we need to
know more than that?
But I've probably spent too many years low-level programming.
Okay, that's one reason. Any more? Huh? Huh? :-)

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
Jan 18 '08 #6

P: n/a

"Bart C" <bc@freeuk.comwrote in message news:fI%jj.79153
My own view is the opposite. How can one program without knowing the
bitsize of one's datatypes? But I've probably spent too many years
low-level
programming.
If you've got to interface with assembly, yes, there is no real option other
than to check through the calling code making sure that the bits are as you
want them. I don't think there's an answer; sometimes you want integers the
size of registers, sometimes fixed sizes, and the assembly code is as likely
to know as the calling C code.

However normally you don't. The integer represents something, which is
normally an index into an array (even chars are really usually indices into
glyph tables). So what you need is an integer that can index the biggest
array possible, and is also fast. Which on some architectures is a bit of a
contradiction, because the vast majority of your arrays will never grow to
more than a hundred items or so, whilst there is a flat memory space that is
many gigabytes in size.
--
Free games and programming goodies.
http://www.personal.leeds.ac.uk/~bgy1mm

Jan 18 '08 #7

P: n/a
eu*****@gmail.com wrote:
If I want just a signed integer with at least 16 width, then why
choose int instead of int_fast16_t? int_fast16_t is the "fastest"
signed integer type that has at least 16 width, while int is simply a
signed integer type that has at least 16 width.
Two reasons:
1 int is everywhere.
int_fast16_t isn't avaailable on all C implementations.
2 int exactly fits the description of what you said you wanted
"want just a signed integer with at least 16 width"

--
pete
Jan 18 '08 #8

P: n/a
"Richard Heathfield" <rj*@see.sig.invalidwrote in message
news:nI******************************@bt.com...
Bart C said:
>How can one program without knowing the bitsize of one's datatypes?

We know the minimum value range of our data types - why would we need to
know more than that?
For ... performance?

If I know I need, say, 32-bits, but not 64-bits which would be an overkill,
what do I use? int could be only 16. long int is at least 32 but could be
64.

I would have to choose long int but at the risk of being inefficient (I
might need a few hundred million of them).

If I distribute an appl as source code I don't have control of the final
size unless I specify the exact compiler and version.

So it's necessary to use alternatives, like the stuff in stdint.h.

--
Bart
Jan 18 '08 #9

P: n/a
Bart C said:
"Richard Heathfield" <rj*@see.sig.invalidwrote in message
news:nI******************************@bt.com...
>Bart C said:
>>How can one program without knowing the bitsize of one's datatypes?

We know the minimum value range of our data types - why would we need to
know more than that?

For ... performance?
<shrugFor some, maybe. I generally find that simply selecting good
algorithms is sufficient to give me "good-enough" performance. Yeah,
absolutely, there are some situations where you need to hack every last
spare clock out, but they are not as common as people like to imagine. I'd
rather write clear code than fast code (which doesn't mean I don't like my
code to be fast). And in any case, when you start selecting types based on
their performance, it won't be long before you discover that what's faster
on one machine could well turn out to be slower on another.

<snip>
So it's necessary to use alternatives, like the stuff in stdint.h.
If you'd said that *you* find it necessary, okay, I'd have to accept that,
obviously. I don't think I've ever found it necessary, though.

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
Jan 18 '08 #10

P: n/a
On Jan 18, 6:41 am, Richard Heathfield <r...@see.sig.invalidwrote:
Bart C said:
"Richard Heathfield" <r...@see.sig.invalidwrote in message
news:nI******************************@bt.com...
Bart C said:
>How can one program without knowing the bitsize of one's datatypes?
We know the minimum value range of our data types - why would we need to
know more than that?
For ... performance?

<shrugFor some, maybe. I generally find that simply selecting good
algorithms is sufficient to give me "good-enough" performance. Yeah,
absolutely, there are some situations where you need to hack every last
spare clock out, but they are not as common as people like to imagine. I'd
rather write clear code than fast code (which doesn't mean I don't like my
code to be fast). And in any case, when you start selecting types based on
their performance, it won't be long before you discover that what's faster
on one machine could well turn out to be slower on another.
[snip]

The problem with signed char and [unsigned] (short|int|long|long long)
is that they are too general purpose. They are at an awkward
not-very-useful spot between the super-high-level "give me an integer
object in which I can store any integer value" and the super-low-level
"give me this many bits that I can play with". As a result, what seems
to have happened in practice is that different camps have created
their own de-facto purposes for some of these types. For example in
the world of Windows, long is essentially a type that has exactly 32
bits. Elsewhere, long may be the de-facto 64-bit type.

For portable code, this can become detrimental to efficiency. If I
want a fast type with at least 32-bit range, C90 says I should choose
long. This might end up being a good choice for one compiler, but on
another compiler where long has another de-facto purpose for long that
causes long to be significantly less efficient than another available
at-least-32-bit type, then half of the intent behind my choice of long
has been ruined.

If you argue against the preceding paragraph by saying "you should not
be so concerned about efficiency", then I think your reasoning is a
very short step away from concluding that we can discard our worries
about type ranges and efficiency and simply use only intmax_t and
uintmax_t everywhere. Surely this is not the level of abstraction that
C is intended for.

This is the reasoning that has led me to conclude that the
[u]int_(fast|least)N types are more useful than signed char and
[unsigned] (short|int|long|long long). They allow me to state my
entire intent instead of stating only half of it and hoping the other
half works out. Having types that allow me to say "I want the
(fastest|smallest) type that gives me at least N bits" is more useful
than having types that only allow me to say "I want a type that gives
me at least N bits".
Jan 18 '08 #11

P: n/a
Bart C wrote, On 18/01/08 11:03:

<snip>
My own view is the opposite. How can one program without knowing the bitsize
of one's datatypes?
A lot of the time, very easily.
But I've probably spent too many years low-level
programming.
Possibly.
I gave one example in c.l.c recently of a long int datatype that was either
32 or 64-bits depending on compiler -- on the same processor. So if you port
a supposedly portable program from one compiler to another, it could run
much slower (or faster).
It could run much slower of faster due to the quality of implementation
of the standard library as well.
Anyway for interfacing with other (binary) software, the exact sizes of
datatypes becomes important. Or (in my case) trying to interface from
another language to C.
Often you *still* don't need to know. I can interface C and C++ without
needing to know, all I need to know is that the compilers that I am
using for the two languages use the same sizes, not what they are. If it
is simply a binary library designed for C on my platform then again all
I need to know is the types (which should be specified in a header file)
and not their sizes.

There *are* times when you need to know, and there are times when you
need to know a type has at least a specific range, but a lot of the time
you do not care if it is larger.
--
Flash Gordon
Jan 18 '08 #12

P: n/a
Richard Heathfield wrote, On 18/01/08 11:29:
Flash Gordon said:
>Malcolm McLean wrote, On 18/01/08 09:09:
<snip things Richard and I agree or agree to disagree on>
>>Once you start inventing types like int_fast16_t people will use them,
and the language becomes more and more difficult to read.
In *your* opinion.

I think he has a point. At the very least, it becomes *uglier* to read. C
as it stands, if well-written, is at least a relatively elegant language,
not just technically and syntactically but also visually. All these
stretched-out underscore-infested type names will be a real nuisance when
scanning quickly through unfamiliar code.
That, in my opinion, is an argument over the chosen names rather than
the addition of the types. Personally I don't find underscores in names
a problem for scanning, especially once I have learnt the patterns.
--
Flash Gordon
Jan 18 '08 #13

P: n/a
eu*****@gmail.com wrote:
char and unsigned char have specific purposes: char is useful for
representing characters of the basic execution character set and
unsigned char is useful for representing the values of individual
bytes. The remainder of the standard integer types are general
purpose. Their only requirement is to satisfy a minimum range of
values, and also int "has the natural size suggested by the
architecture of the execution environment". What are the reasons for
using these types instead of the [u]int_fastN_t types of <stdint.h>?
Keep in mind that the C type system grew over decades. The committee
considers backwards compatibility to be very important (IMO, correctly),
but it has also attempted to alleviate some of the problems associated
with the original language design. As a result of those conflicting
goals, C has a lot of internal inconsistencies.

If it had been designed from scratch with something similar to the
current result in mind, we would probably have only the size-named types
from stdint.h, they wouldn't require a special header, and they'd
probably have simpler, shorter names. Aside from the fact that their
names are easier to type, char, short, int, and don't have any inherent
advantage over the size-named types.

If and when C99 gets fully adopted by most mainstream compilers and
programmers, the main remaining reason for using char, short, int, or
long, will be that your code must be compatible with an interface
defined in terms of those types. That applies to almost the entire C
standard library, as well as large parts of most of the other libraries
I've used.
Jan 18 '08 #14

P: n/a
<eu*****@gmail.comwrote in message news:
On Jan 18, 6:41 am, Richard Heathfield <r...@see.sig.invalidwrote:
>Bart C said:
"Richard Heathfield" <r...@see.sig.invalidwrote in message
news:nI******************************@bt.com...
Bart C said:
>>How can one program without knowing the bitsize of one's datatypes?
>We know the minimum value range of our data types - why would we need
to
know more than that?
For ... performance?

<shrugFor some, maybe. I generally find that simply selecting good
algorithms is sufficient to give me "good-enough" performance. Yeah,
absolutely, there are some situations where you need to hack every last
spare clock out, but they are not as common as people like to imagine.
I'd
rather write clear code than fast code (which doesn't mean I don't like
my
code to be fast). And in any case, when you start selecting types based
on
their performance, it won't be long before you discover that what's
faster
on one machine could well turn out to be slower on another.
[snip]

The problem with signed char and [unsigned] (short|int|long|long long)
is that they are too general purpose. They are at an awkward
not-very-useful spot between the super-high-level "give me an integer
object in which I can store any integer value" and the super-low-level
"give me this many bits that I can play with". As a result, what seems
to have happened in practice is that different camps have created
their own de-facto purposes for some of these types. For example in
the world of Windows, long is essentially a type that has exactly 32
bits. Elsewhere, long may be the de-facto 64-bit type.

For portable code, this can become detrimental to efficiency. If I
want a fast type with at least 32-bit range, C90 says I should choose
long. This might end up being a good choice for one compiler, but on
another compiler where long has another de-facto purpose for long that
causes long to be significantly less efficient than another available
at-least-32-bit type, then half of the intent behind my choice of long
has been ruined.

If you argue against the preceding paragraph by saying "you should not
be so concerned about efficiency", then I think your reasoning is a
very short step away from concluding that we can discard our worries
about type ranges and efficiency and simply use only intmax_t and
uintmax_t everywhere. Surely this is not the level of abstraction that
C is intended for.

This is the reasoning that has led me to conclude that the
[u]int_(fast|least)N types are more useful than signed char and
[unsigned] (short|int|long|long long). They allow me to state my
entire intent instead of stating only half of it and hoping the other
half works out. Having types that allow me to say "I want the
(fastest|smallest) type that gives me at least N bits" is more useful
than having types that only allow me to say "I want a type that gives
me at least N bits".
I absolutely agree.
I think we are creating a mess with all these integer types and conventions
on how they should be used.

However generally I want an integer which can index or count an array, and
is fast, and is signed, because intermediate calculations might go below
zero.
This is usually semi-achievable. There will be a fast type the same width as
the address bus, the one bit we can ignore as we are unlikely to want a char
array taking up half memory (we can always resort to "unsigned" for that
special situation), but it might not be the fastest type, and most arrays
will in fact be a lot smaller than the largest possible array.

--
Free games and programming goodies.
http://www.personal.leeds.ac.uk/~bgy1mm

--
Free games and programming goodies.
http://www.personal.leeds.ac.uk/~bgy1mm

Jan 18 '08 #15

P: n/a
Flash Gordon said:
Richard Heathfield wrote, On 18/01/08 11:29:
<snip>
>At the very least, [C with new integer types] becomes *uglier* to read.
C as it stands, if well-written, is at least a relatively elegant
language, not just technically and syntactically but also visually. All
these stretched-out underscore-infested type names will be a real
nuisance when scanning quickly through unfamiliar code.

That, in my opinion, is an argument over the chosen names rather than
the addition of the types.
Yes, it is. My argument against the new types *was* that they are
unnecessary, but I accept that what I really mean is that *I* don't see a
need for them in the kind of code I tend to write. If they will bring real
benefits to other C programmers, well, they're a wart I can live with,
since at least I won't have to come across it all that often, and then
only in other people's code, not my own.

But they could have found better names, surely? Abigail, for instance. Or
Rhododendron.

Yeah, all right, maybe not those precise names... :-)
Personally I don't find underscores in names
a problem for scanning, especially once I have learnt the patterns.
Is ugliness a problem? I guess ugliness is in the eye of the beholder.

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
Jan 18 '08 #16

P: n/a
eu*****@gmail.com said:

<snip>
If I
want a fast type with at least 32-bit range, C90 says I should choose
long. This might end up being a good choice for one compiler, but on
another compiler where long has another de-facto purpose for long that
causes long to be significantly less efficient than another available
at-least-32-bit type, then half of the intent behind my choice of long
has been ruined.

If you argue against the preceding paragraph by saying "you should not
be so concerned about efficiency",
It depends. :-) We cannot and should not *ignore* efficiency.
Nevertheless, there is more to life than speed. Correctness, clarity,
generality and portability are all important too. But, as I said before,
there *are* occasions when you need to push the hardware as fast as it
will go. I do accept that.

<snip>

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
Jan 18 '08 #17

P: n/a
Malcolm McLean wrote, On 18/01/08 12:19:
>
"Bart C" <bc@freeuk.comwrote in message news:fI%jj.79153
>My own view is the opposite. How can one program without knowing the
bitsize of one's datatypes? But I've probably spent too many years
low-level
programming.
<snip>
However normally you don't. The integer represents something, which is
normally an index into an array (even chars are really usually indices
into glyph tables).
Please be aware that Malcolm seems to be the only person who thinks this.
So what you need is an integer that can index the
biggest array possible, and is also fast. Which on some architectures is
a bit of a contradiction, because the vast majority of your arrays will
never grow to more than a hundred items or so, whilst there is a flat
memory space that is many gigabytes in size.
As a result Malcolm seems to be the only person who thinks this.

The flaws in Malcolm's arguments have been pointed out many times so you
should be able to find them using Google.
--
Flash Gordon
Jan 18 '08 #18

P: n/a
Malcolm McLean wrote, On 18/01/08 13:25:
<eu*****@gmail.comwrote in message news:
>On Jan 18, 6:41 am, Richard Heathfield <r...@see.sig.invalidwrote:
>>Bart C said:

"Richard Heathfield" <r...@see.sig.invalidwrote in message
news:nI******************************@bt.com.. .
Bart C said:

How can one program without knowing the bitsize of one's datatypes?

We know the minimum value range of our data types - why would we
need >to
know more than that?

For ... performance?

<shrugFor some, maybe. I generally find that simply selecting good
algorithms is sufficient to give me "good-enough" performance. Yeah,
absolutely, there are some situations where you need to hack every last
spare clock out, but they are not as common as people like to
imagine. I'd
rather write clear code than fast code (which doesn't mean I don't
like my
code to be fast). And in any case, when you start selecting types
based on
their performance, it won't be long before you discover that what's
faster
on one machine could well turn out to be slower on another.
[snip]

The problem with signed char and [unsigned] (short|int|long|long long)
is that they are too general purpose. They are at an awkward
not-very-useful spot between the super-high-level "give me an integer
object in which I can store any integer value" and the super-low-level
"give me this many bits that I can play with". As a result, what seems
to have happened in practice is that different camps have created
their own de-facto purposes for some of these types. For example in
the world of Windows, long is essentially a type that has exactly 32
bits. Elsewhere, long may be the de-facto 64-bit type.

For portable code, this can become detrimental to efficiency. If I
want a fast type with at least 32-bit range, C90 says I should choose
long. This might end up being a good choice for one compiler, but on
another compiler where long has another de-facto purpose for long that
causes long to be significantly less efficient than another available
at-least-32-bit type, then half of the intent behind my choice of long
has been ruined.

If you argue against the preceding paragraph by saying "you should not
be so concerned about efficiency", then I think your reasoning is a
very short step away from concluding that we can discard our worries
about type ranges and efficiency and simply use only intmax_t and
uintmax_t everywhere. Surely this is not the level of abstraction that
C is intended for.

This is the reasoning that has led me to conclude that the
[u]int_(fast|least)N types are more useful than signed char and
[unsigned] (short|int|long|long long). They allow me to state my
entire intent instead of stating only half of it and hoping the other
half works out. Having types that allow me to say "I want the
(fastest|smallest) type that gives me at least N bits" is more useful
than having types that only allow me to say "I want a type that gives
me at least N bits".
I absolutely agree.
Do you realise you are agreeing to having several integer types? I
though you wanted there to be only a single one size fits hardly anyone
integer type!
I think we are creating a mess with all these integer types and
conventions on how they should be used.
Urm, he was just saying to use the new types which you say make things work!
However generally I want an integer which can index or count an array,
and is fast, and is signed, because intermediate calculations might go
below zero.
Unsigned arithmetic handles that nicely, but to meet your desires I
suggest you use ptrdiff_t and size_t as appropriate. These types have
been there since at least the 1989 standard was implemented.
This is usually semi-achievable. There will be a fast type the same
width as the address bus, the one bit we can ignore as we are unlikely
to want a char array taking up half memory (we can always resort to
"unsigned" for that special situation), but it might not be the fastest
type, and most arrays will in fact be a lot smaller than the largest
possible array.
See above, the types you want have been supported for a long time. If
you don't like the spelling you can typedef them to something else.
--
Flash Gordon
Jan 18 '08 #19

P: n/a
Richard Heathfield wrote, On 18/01/08 13:37:
Flash Gordon said:
>Richard Heathfield wrote, On 18/01/08 11:29:
<snip discussion of types in stdint.h>

I think we reached this point before.
But they could have found better names, surely? Abigail, for instance. Or
Rhododendron.

Yeah, all right, maybe not those precise names... :-)
Of course not those names, they should be Brenda, Heather... ;-)
>Personally I don't find underscores in names
a problem for scanning, especially once I have learnt the patterns.

Is ugliness a problem? I guess ugliness is in the eye of the beholder.
It is indeed. I'm so used to underscores in names that I don't see them
as such I just see N words grouped together.
--
Flash Gordon
Jan 18 '08 #20

P: n/a

"Flash Gordon" <sp**@flash-gordon.me.ukwrote in message
See above, the types you want have been supported for a long time. If you
don't like the spelling you can typedef them to something else.
bool breaks libraries.

If ANSI decides that "s64" shall be the name of a new type, that's fine. If
I define it myself, either the whole world adopts my convention, which is to
say I have usurrped ANSI / ISO, or it is a nuisance to everybody trying to
call or read my code.
--
Free games and programming goodies.
http://www.personal.leeds.ac.uk/~bgy1mm

Jan 18 '08 #21

P: n/a
Flash Gordon wrote:
>
There *are* times when you need to know, and there are times when you
need to know a type has at least a specific range, but a lot of the time
you do not care if it is larger.
Rarely.

If I write

int a = 45000;

that will not work in 16 bit implementations.

You HAVE to know the bitsize to know how much data
you can put into an integer!

Potentially, all assignments are affected unless
you never use integer data bigger than 32767.
--
jacob navia
jacob at jacob point remcomp point fr
logiciels/informatique
http://www.cs.virginia.edu/~lcc-win32
Jan 18 '08 #22

P: n/a
Richard Heathfield wrote:
Bart C said:
>How can one program without knowing the bitsize of one's datatypes?

We know the minimum value range of our data types - why would we need to
know more than that?
>But I've probably spent too many years low-level programming.

Okay, that's one reason. Any more? Huh? Huh? :-)
Consider

int i = 38700;

If you do not care about int size you will never know that
this will not work in 16 bit implementations, or (worst)
i will be initialized to something completely different.

Of course YOU never use data bigger than 32767, as everyone knows.

:-)
--
jacob navia
jacob at jacob point remcomp point fr
logiciels/informatique
http://www.cs.virginia.edu/~lcc-win32
Jan 18 '08 #23

P: n/a
jacob navia said:
Flash Gordon wrote:
>>
There *are* times when you need to know, and there are times when you
need to know a type has at least a specific range, but a lot of the time
you do not care if it is larger.

Rarely.

If I write

int a = 45000;

that will not work in 16 bit implementations.
That is not a counter-example to Flash's point. If you need an integer type
that can store 45000, then "you need to know a type has at least a
specific range". Since the least range for int is -32767 to +32767, you
know that this won't do in portable code, so you move up to long int:

long int a = 45000;

This will work just fine in 16 bit implementations, no matter how big a
long int is, because it *must* have at least 32 bits.
You HAVE to know the bitsize to know how much data
you can put into an integer!
No, you have to know whether the value you wish to store will fit into the
range for a given type. If so, it doesn't matter how many /more/ bits it
has. And if not, it still doesn't matter how many bits it has - if your
value doesn't fit, it doesn't fit.
Potentially, all assignments are affected unless
you never use integer data bigger than 32767.
Right, which is why we have this thing called long int.

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
Jan 18 '08 #24

P: n/a
jacob navia said:

<snip>
Consider

int i = 38700;
Why? It's not guaranteed to work. Instead, consider:

long int i = 38700;

which *is* guaranteed to work.
If you do not care about int size you will never know that
this will not work in 16 bit implementations, or (worst)
i will be initialized to something completely different.
I don't know whose point you're arguing against, but the above response
does not address any statement I have made.
Of course YOU never use data bigger than 32767, as everyone knows.
Not so. But when I do, I use long int. And if I need values higher than
2147483647 and know they can't be negative, I'll use unsigned long int.
And if I need values higher than 4294967295, I'll use my bignum library.

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
Jan 18 '08 #25

P: n/a
Malcolm McLean wrote, On 18/01/08 15:21:
>
"Flash Gordon" <sp**@flash-gordon.me.ukwrote in message
>See above, the types you want have been supported for a long time. If
you don't like the spelling you can typedef them to something else.
bool breaks libraries.
So don't use it. Use _Bool if you want instead. There is not requirement
for you to #include <stdbool.hto use the new boolean type.
If ANSI decides that "s64" shall be the name of a new type, that's fine.
If I define it myself, either the whole world adopts my convention,
which is to say I have usurrped ANSI / ISO, or it is a nuisance to
everybody trying to call or read my code.
Misusing int as you are want to do causes problems.

Either get yourself on the standard committee and try and get the
language changed
Or find a language that is defined as you want and use that
Or write your own language and use that
Or put up with the language as it is defined.

In any case, by your definition of what is wrong it was wrong in the
1989 standard so stop complaining that these things are rapidly
destroying the language, since that is patently false.
--
Flash Gordon
Jan 18 '08 #26

P: n/a

"jacob navia" <ja***@nospam.comwrote in message
>
If I write

int a = 45000;

that will not work in 16 bit implementations.

You HAVE to know the bitsize to know how much data
you can put into an integer!
The question is, why do you want an integer equal to 45000?
We can thinks of lots of possible reasons, but a good one might be that you
have 45000 customer records you wish to read into memory.
Which means that you need 45000 * N bytes of contiguous storage, which most
machines will happily provide for fairly reasonable values of N. But not 16
bit machines.
As long as int is the same as a pointer and memory space is flat, everything
is fine.
--
Free games and programming goodies.
http://www.personal.leeds.ac.uk/~bgy1mm
Jan 18 '08 #27

P: n/a
eu*****@gmail.com wrote:
>
.... snip ...
>
For portable code, this can become detrimental to efficiency. If I
want a fast type with at least 32-bit range, C90 says I should
choose long. This might end up being a good choice for one
compiler, but on another compiler where long has another de-facto
purpose for long that causes long to be significantly less
efficient than another available at-least-32-bit type, then half
of the intent behind my choice of long has been ruined.

If you argue against the preceding paragraph by saying "you should
not be so concerned about efficiency", then I think your reasoning
is a very short step away from concluding that we can discard our
worries about type ranges and efficiency and simply use only
intmax_t and uintmax_t everywhere. Surely this is not the level of
abstraction that C is intended for.
I think you have exagerrated the problem. In general there will
only be one beast where you have to be critical of the exact size.
You should set up your own type, and alias it to the appropriate
standard type by using limits.h and conditional defines. Then
write your code in terms of that type. Note that this also allows
for use of other than the multiple of 8 sizes.

--
[mail]: Chuck F (cbfalconer at maineline dot net)
[page]: <http://cbfalconer.home.att.net>
Try the download section.

--
Posted via a free Usenet account from http://www.teranews.com

Jan 18 '08 #28

P: n/a
Bart C wrote:
"Richard Heathfield" <rj*@see.sig.invalidwrote:
>Bart C said:
>>How can one program without knowing the bitsize of one's datatypes?

We know the minimum value range of our data types - why would we
need to know more than that?

For ... performance?

If I know I need, say, 32-bits, but not 64-bits which would be an
overkill, what do I use? int could be only 16. long int is at
least 32 but could be 64.

I would have to choose long int but at the risk of being
inefficient (I might need a few hundred million of them).
The basic problem here is historic. C was organized to allow for
16 bit processors, which lead to the 16 bit minimum size for ints.
Without that the minimum sizes for short, int, long could have been
16, 32, 64, and long long would never have arisen. We can't change
the minima without breaking all sorts of programs.

At least the situation is such that there can be no more than one
trap value for 16 bit ints. :-)

--
[mail]: Chuck F (cbfalconer at maineline dot net)
[page]: <http://cbfalconer.home.att.net>
Try the download section.

--
Posted via a free Usenet account from http://www.teranews.com

Jan 18 '08 #29

P: n/a
Malcolm McLean wrote:
I think we are creating a mess with all these integer types and
conventions on how they should be used.
That's probably inevitable with C having to target every conceivable
hardware and having to maintain compatibility with every line of code ever
written.

My main interest is PCs which are typically 32/64 bits now, and will be at
least that for the foreseeable future. So I don't really care about anything
other than 8,16,32,64 bits. (And it can't be a coincidence that these sizes
figure heavily in stdint.h.).
However generally I want an integer which can index or count an
array, and is fast, and is signed, because intermediate calculations
might go below zero.
This is usually semi-achievable. There will be a fast type the same
width as the address bus, the one bit we can ignore as we are
unlikely to want a char array taking up half memory (we can always
resort to "unsigned" for that special situation), but it might not be
the fastest type, and most arrays will in fact be a lot smaller than
the largest possible array.
The number of (physical) address bits appearing on the cpu pinouts is
unlikely to be a full 64 bits. Even virtual address spaces are a lot less
than 64-bits I would guess.

(64-bits addresses a *lot* of memory. It might just be enough to address all
the memory in every desktop PC in the world.)

If your task-space is 4GB or less than your array indexes/indices, size-t's
and so on don't need to be more than 32-bit unsigned. But your file-system
is likely to need 64-bits.

(Actually 48-bits will probably suffice for most purposes but that is too
odd a figure.)

--
Bart


Jan 18 '08 #30

P: n/a
"Bart C" <bc@freeuk.comwrote in message
Malcolm McLean wrote:
>I think we are creating a mess with all these integer types and
conventions on how they should be used.

That's probably inevitable with C having to target every conceivable
hardware and having to maintain compatibility with every line of code
ever
written.

My main interest is PCs which are typically 32/64 bits now, and will be at
least that for the foreseeable future. So I don't really care about
anything
other than 8,16,32,64 bits. (And it can't be a coincidence that these
sizes
figure heavily in stdint.h.).
Yes. In reality we have 8 bit, 16 bit, 32 bit and 64 bit integers to worry
about. And somehow we've managed to create a zoo of types.
>
The number of (physical) address bits appearing on the cpu pinouts is
unlikely to be a full 64 bits. Even virtual address spaces are a lot less
than 64-bits I would guess.

(64-bits addresses a *lot* of memory. It might just be enough to address
all the memory in every desktop PC in the world.)

If your task-space is 4GB or less than your array indexes/indices,
size-t's
and so on don't need to be more than 32-bit unsigned. But your file-system
is likely to need 64-bits.

(Actually 48-bits will probably suffice for most purposes but that is too
odd a figure.)
48 bits is probably enough, but let's go with 64.
64 bits will address every byte on the biggest hard drive in the world, for
the conceivable future. So if integer calculations are in 64 bits, we should
have no problems.
Unfortunately there are speed considerations. But if a computer has more
than 4GB of addressible memory, these can't be too serious. There must be a
fast way of addressing all 5GB, or the processor is not of much practical
use. So 64 bits can be the default, which you use almost everywhere, except
in very tight inner loops where maybe speed matters, and except for special
data - raw audio data is traditionally 16 bits per sample, for example, you
wouldn't normally want to quadruple memory take. You do need other types,
but only rarely.

--
Free games and programming goodies.
http://www.personal.leeds.ac.uk/~bgy1mm

Jan 18 '08 #31

P: n/a
On Jan 17, 3:49 pm, eule...@gmail.com wrote:
char and unsigned char have specific purposes: char is useful for
representing characters of the basic execution character set and
unsigned char is useful for representing the values of individual
bytes. The remainder of the standard integer types are general
purpose. Their only requirement is to satisfy a minimum range of
values, and also int "has the natural size suggested by the
architecture of the execution environment". What are the reasons for
using these types instead of the [u]int_fastN_t types of <stdint.h>?
The (u)int_fast<N>_t types? I imagine the C language committee will
make up some rationale that was voiced by some vendor who had some
specific reason for wanting to steer programmers into the direction of
using them for some specific application. This ignores, of course (as
the committee is prone to doing), the fact that a compatible system
created by a different vendor might want a different set of integer
types to be used.

Personally I highly recommend that users stay away from using the
(u)int_fast<N>_t since the just puts programmers in the same position
of not knowing what you've really got that using int and long does to
you. The compiler cannot definitively make a policy about what
integers are fast or not before the programmers have even begun to
write code.
If I want just a signed integer with at least 16 width, then why
choose int instead of int_fast16_t? int_fast16_t is the "fastest"
signed integer type that has at least 16 width, while int is simply a
signed integer type that has at least 16 width. It seems that choosing
int_fast16_t is at least as good as choosing int. This argument can be
made for N=8,16,32,64, and for the corresponding unsigned types.
Presumably a system might have a way of emulating 32 bits exactly that
is slow (but for compatibility reasons is chosen as the type for
[unsigned] long), but can perform with 40 bits somewhat faster even
though the int type is only 16 bits. It might be best for picking the
40 bit integer type for an inner loop, while the 32 bit integer type
for storing in a data structure that you want to fit into a cache, or
be externally compatible with other systems.
<stdint.halso offers [u]int_leastN_t types, which are useful when
keeping a small storage size is the greatest concern.
Yeah. Its pretty unusual that I would use them though. I don't know
when anyone else would.
The only benefit of using the standard integer types I can see is that
their ranges may expand as the C standard progresses, so code that
uses them might stay useful over time.
Well, I use int when I really don't need to know its specific size and
I don't have a need to go over 32767. Similarly for long. They are
also needed for backward compatibility (stdint.h is a new thing from
C99, and has been added to some non-C99 compilers (gcc, Intel, Open
Watcom for example, but not Visual C++).)
[...] For example fseek of <stdio.h>
uses a long for its offset parameter, so if the range of long grows
then fseek will automatically offer a wider range of offsets.
Right except that this is nonsense as I and others have posted
before. "long" has to retain system compatibility even as file
systems change over time. intmax_t (a type which is practically
guaranteed to change as the compiler changes) is the only possible
correct type to use for file system offsets.
It's also interesting to note (or maybe not) that in the Windows
world, the idea of long being general purpose has somewhat been
destroyed and long has become a type that must have exactly 32 bits.
This has been destroyed on *ALL* systems which have made a transition
from one bitness to another (16->32 or 32->64, as typical examples.)
I am unaware of any compiler which, upon upgrading, simply changed the
size of one of the integer types just to correspond to the underlying
system's new capabilities.

stdint.h has been necessary for C from the very beginning, but this
reality only dawned on the committee in 1999. Of course now that the
industry has basically rejected C99 (for other reasons) we are left
without a pervasive stdint.h interface that we can reliably use. I
have personally done what I can to rectify this situation by making
http://www.pobox.com/~qed/pstdint.h publicly available. (If you use
it and notice that it doesn't work on your system please help me
update it.)

--
Paul Hsieh
http://www.pobox.com/~qed/
http://bstring.sf.net/
Jan 18 '08 #32

P: n/a
On Jan 18, 3:32 am, Richard Heathfield <r...@see.sig.invalidwrote:
Bart C said:
How can one program without knowing the bitsize of one's datatypes?

We know the minimum value range of our data types - why would we need to
know more than that?
You want to do math in a ring, without knowing what ring you are in?
More specifically: exactly how integers wrap around matters to a large
class of applications (like those that accept input.)

The reason why questions like this are cropping up is because of the
transition from 32 bits to 64 bits which is happening right now.
People want to know if they can still get away with using just 32 bits
with just a little more work, and not break their backwards
compatibility by pushing everything to 64 bits -- but doing so means
they need to *know* when their integers wrap around.
But I've probably spent too many years low-level programming.

Okay, that's one reason. Any more? Huh? Huh? :-)
How about creating a big integer library? How are you supposed to
capture/detect a carry if your underlying system happens to be
capturing it for you in extra integer bits it happened to magically
give you?

This also seriously affects some algorithms like primality testing.
If you know the size of your integers is less than 36 bits, there are
well known fast algorithms that can test for primality
deterministically in finite time. If its more bits, then they only
work *nearly all the time*. So if you implement:

long factor (long n) {
long f;
if (isPrimeUpTo36bits (n)) return 1; /* Not factorable */
f = quickDivisor (n);
if (f 1) return f;
for (f=3; ; f+=2) {
if (0 == (n % f)) return f;
}
}

How do you even know if the algorithm terminates? If the system
decides that long is 40 bits, then it does not terminate. If the
system decides that long is 32 bits then it does.

We could force this to work by putting an extra condition in the for
loop which might cost in terms of performance. (It actually doesn't
in this case, but the (n % f) can be modified in a sort of "strength
reduction" way (using code much to complicated for a quick USENET
post) where it *does* matter.)

--
Paul Hsieh
http://www.pobox.com/~qed/
http://bstring.sf.net/
Jan 18 '08 #33

P: n/a
jxh
On Jan 18, 3:29*am, Richard Heathfield <r...@see.sig.invalidwrote:
...
I think he has a point. At the very least, it becomes
*uglier* to read. C as it stands, if well-written, is at
least a relatively elegant language, not just technically
and syntactically but also visually. All these stretched-out
underscore-infested type names will be a real nuisance when
scanning quickly through unfamiliar code.
I think it would have been nicer to extend the C syntax to allow
bit-field style specifiers for regular integral objects.

unsigned int u16 : 16; /* u16 takes up 16 bits */

-- James
Jan 18 '08 #34

P: n/a
Paul Hsieh wrote:
On Jan 18, 3:32 am, Richard Heathfield <r...@see.sig.invalidwrote:
Bart C said:
How can one program without knowing the bitsize of one's datatypes?
We know the minimum value range of our data types - why would we need to
know more than that?

You want to do math in a ring, without knowing what ring you are in?
More specifically: exactly how integers wrap around matters to a large
class of applications (like those that accept input.)
If wrap-around is important to your program, then yes, you need an
exact-sized type. I would disagree that wrap-around is needed for any
program that does input. In most of the programs I've ever written,
wrap around is something to be avoided, not something to be used.
Knowing the minimum ranges of a data type, and having symbolic access
(through limits.h) to the actual ranges, is sufficient for avoiding
wrap-around.
Jan 18 '08 #35

P: n/a
jameskuy...@verizon.net wrote:
....
.... I would disagree that wrap-around is needed for any
program that does input. ...
That should have been "every", not "any".
Jan 18 '08 #36

P: n/a
CBFalconer wrote:
eu*****@gmail.com wrote:
.... snip ...
>For portable code, this can become detrimental to efficiency. If I
want a fast type with at least 32-bit range, C90 says I should
choose long. This might end up being a good choice for one
compiler, but on another compiler where long has another de-facto
purpose for long that causes long to be significantly less
efficient than another available at-least-32-bit type, then half
of the intent behind my choice of long has been ruined.

If you argue against the preceding paragraph by saying "you should
not be so concerned about efficiency", then I think your reasoning
is a very short step away from concluding that we can discard our
worries about type ranges and efficiency and simply use only
intmax_t and uintmax_t everywhere. Surely this is not the level of
abstraction that C is intended for.

I think you have exagerrated the problem. In general there will
only be one beast where you have to be critical of the exact size.
You should set up your own type, and alias it to the appropriate
standard type by using limits.h and conditional defines. Then
write your code in terms of that type.
Isn't that what <stdint.hdoes for you in a standardised form?
Note that this also allows
for use of other than the multiple of 8 sizes.
Eh?

--
Ian Collins.
Jan 18 '08 #37

P: n/a
Malcolm McLean wrote:
>
"jacob navia" <ja***@nospam.comwrote in message
>>
If I write

int a = 45000;

that will not work in 16 bit implementations.

You HAVE to know the bitsize to know how much data
you can put into an integer!
The question is, why do you want an integer equal to 45000?
We can thinks of lots of possible reasons, but a good one might be that
you have 45000 customer records you wish to read into memory.
Which means that you need 45000 * N bytes of contiguous storage, which
most machines will happily provide for fairly reasonable values of N.
But not 16 bit machines.
As long as int is the same as a pointer and memory space is flat,
everything is fine.
Even on a 16 bit machine where int is the same as a pointer and memory
space is flat? You appear to have contradicted yourself.

--
Ian Collins.
Jan 18 '08 #38

P: n/a
On Jan 18, 8:32 am, Richard Heathfield <r...@see.sig.invalidwrote:
jacob navia said:

<snip>
Consider
int i = 38700;
(This has the additional problem the on most 32-bit compilers where it
*does* work, it will *not* give you a warning indicating that this is
not portable.)
Why? It's not guaranteed to work. Instead, consider:

long int i = 38700;

which *is* guaranteed to work.
It also might be unnecessarily slow. You are letting the compiler
vendor make decisions for you.

int32_t i = 38700;

is also guaranteed to work, and is totally non-controversial about
what it means or is doing.
If you do not care about int size you will never know that
this will not work in 16 bit implementations, or (worst)
i will be initialized to something completely different.

I don't know whose point you're arguing against, but the above response
does not address any statement I have made.
Of course YOU never use data bigger than 32767, as everyone knows.

Not so. But when I do, I use long int. And if I need values higher than
2147483647 and know they can't be negative, I'll use unsigned long int.
And if I need values higher than 4294967295, I'll use my bignum library.
So 1) you are dismissing the possibility of using floating point. 2)
Either your bignum library has support for file offsets or you have
vowed not to support the platform specific extensions for dealing with
file offsets on your machine.

--
Paul Hsieh
http://www.pobox.com/~qed/
http://bstring.sf.net/
Jan 18 '08 #39

P: n/a
Paul Hsieh said:
On Jan 18, 3:32 am, Richard Heathfield <r...@see.sig.invalidwrote:
>Bart C said:
How can one program without knowing the bitsize of one's datatypes?

We know the minimum value range of our data types - why would we need to
know more than that?

You want to do math in a ring, without knowing what ring you are in?
If it matters (which it doesn't always), it is wise to select the ring
precisely, by applying appropriate mathematical operations.
More specifically: exactly how integers wrap around matters to a large
class of applications (like those that accept input.)
Unsigned integers wrap around to 0 at U<TYPE>_MAX + 1. As long as I know
that, either it's good enough (in which case that's fine), or it isn't, in
which case I have to force the behaviour I want (see above).

For signed integers, overflow invokes undefined behaviour anyway, so the
matter doesn't arise.

<snip>
But I've probably spent too many years low-level programming.

Okay, that's one reason. Any more? Huh? Huh? :-)

How about creating a big integer library?
Done that. Didn't need fixed size ints. Next question.
This also seriously affects some algorithms like primality testing.
If you know the size of your integers is less than 36 bits, there are
well known fast algorithms that can test for primality
deterministically in finite time.
I'm trying to think of a use for less-than-36-bit primes, and failing.

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
Jan 18 '08 #40

P: n/a
Richard Heathfield wrote:
Paul Hsieh said:
>On Jan 18, 8:32 am, Richard Heathfield <r...@see.sig.invalidwrote:
>>Instead, consider:

long int i = 38700;

which *is* guaranteed to work.
It also might be unnecessarily slow. You are letting the compiler
vendor make decisions for you.

int32_t i = 38700;

is also guaranteed to work, and is totally non-controversial about
what it means or is doing.

Provided, of course, that you are one of those lucky people who has a
conforming C99 compiler. I am not one such.
Or working on a POSIX compliant environment where these types are
required.

--
Ian Collins.
Jan 18 '08 #41

P: n/a
Richard Heathfield wrote:
Paul Hsieh said:
>int32_t i = 38700;

is also guaranteed to work, and is totally non-controversial about
what it means or is doing.

Provided, of course, that you are one of those lucky people who has a
conforming C99 compiler. I am not one such.
You are using a gcc version prior to year 2000. You refuse to upgrade,
and then you say here:
Provided, of course, that you are one of those lucky people who has a
conforming C99 compiler. I am not one such.

Poor Heathfield. I will start crying now.

--
jacob navia
jacob at jacob point remcomp point fr
logiciels/informatique
http://www.cs.virginia.edu/~lcc-win32
Jan 18 '08 #42

P: n/a
jacob navia said:
Richard Heathfield wrote:
>Paul Hsieh said:
>>int32_t i = 38700;

is also guaranteed to work, and is totally non-controversial about
what it means or is doing.

Provided, of course, that you are one of those lucky people who has a
conforming C99 compiler. I am not one such.

You are using a gcc version prior to year 2000. You refuse to upgrade,
The version I have is C90-conforming. If gcc/glibc now conformed to C99,
that would be a good reason to upgrade. But it doesn't. So why bother?

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
Jan 18 '08 #43

P: n/a
Paul Hsieh said:
On Jan 18, 2:13 pm, Richard Heathfield <r...@see.sig.invalidwrote:
>Paul Hsieh said:
On Jan 18, 3:32 am, Richard Heathfield <r...@see.sig.invalidwrote:
Bart C said:
How can one program without knowing the bitsize of one's datatypes?
>We know the minimum value range of our data types - why would we need
to know more than that?
You want to do math in a ring, without knowing what ring you are in?

If it matters (which it doesn't always), it is wise to select the ring
precisely, by applying appropriate mathematical operations.

You have to select the type. (Specifically you cannot select Z(2**64)
from just the operations you use -- you have to *declare* a 64 bit
type.)
If you have C99, you can do that, using long long int. (And if like me you
don't, you can't guarantee that a 64-bit type is available.)

<snip>
How about creating a big integer library?

Done that. Didn't need fixed size ints. Next question.

Well, then I certain don't need your big integer library.
No, of course you don't. But I'm fine with it, thanks.
I have no
interest in any big integer library that isn't aware precisely the
details of its base integer type its written on top of.
I use unsigned char, so I know I have at least 8 bits to play with in each
element of the array - which is plenty, thanks.

Anyone who
has written an *OPTIMIZED* big integer library should know the serious
performance impact this has.
Last time I measured its performance was about four years ago (when it
managed to do in just-about-zero-time a task that took five hours on
someone else's bignum. (It's okay, we straightened out why his was taking
so much time). I didn't write it for performance, mind you - I wrote it
for fun, trying to make the code as clear as possible - but it has always
been fast *enough* for any purpose I've found for it.
>I'm trying to think of a use for less-than-36-bit primes, and failing.

Factoring maybe?
Maybe. Not terribly convinced that the four bits of game are worth the
portability candle.

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
Jan 19 '08 #44

P: n/a
Richard Heathfield wrote:
>I have no
interest in any big integer library that isn't aware precisely the
details of its base integer type its written on top of.

I use unsigned char, so I know I have at least 8 bits to play with in each
element of the array - which is plenty, thanks.
Yes, VERY efficient.
You wrote it for fun, and look, it is really comic.

Like your bit string functions in "C unleashed"... a few macros
and "finished". The important thing is that it is portable.
If it is efficient, you do not care.

It is a design philosophy. I do not like it, and I think
that kind of software is maybe portable but it is not worth
spending any effort in it.

But here it is a matter of philosophy.
Anyone who
>has written an *OPTIMIZED* big integer library should know the serious
performance impact this has.

Last time I measured its performance was about four years ago (when it
managed to do in just-about-zero-time a task that took five hours on
someone else's bignum.
Who cares? There is ALWAYS something WORST :-)

(It's okay, we straightened out why his was taking
so much time). I didn't write it for performance, mind you - I wrote it
for fun, trying to make the code as clear as possible - but it has always
been fast *enough* for any purpose I've found for it.
Sure.
>>I'm trying to think of a use for less-than-36-bit primes, and failing.
Factoring maybe?

Maybe. Not terribly convinced that the four bits of game are worth the
portability candle.
This obsession with "portability", as if the end user would care if
his program that takes forever to run is easy to port to some
washing machine or whatever.

Making a bignum library using chars is just ridiculous.

--
jacob navia
jacob at jacob point remcomp point fr
logiciels/informatique
http://www.cs.virginia.edu/~lcc-win32
Jan 19 '08 #45

P: n/a
On Jan 18, 4:05 pm, Richard Heathfield <r...@see.sig.invalidwrote:
Paul Hsieh said:
On Jan 18, 2:13 pm, Richard Heathfield <r...@see.sig.invalidwrote:
Paul Hsieh said:
On Jan 18, 3:32 am, Richard Heathfield <r...@see.sig.invalidwrote:
Bart C said:
How can one program without knowing the bitsize of one's datatypes?
We know the minimum value range of our data types - why would we need
to know more than that?
You want to do math in a ring, without knowing what ring you are in?
If it matters (which it doesn't always), it is wise to select the ring
precisely, by applying appropriate mathematical operations.
You have to select the type. (Specifically you cannot select Z(2**64)
from just the operations you use -- you have to *declare* a 64 bit
type.)

If you have C99, you can do that, using long long int. (And if like me you
don't, you can't guarantee that a 64-bit type is available.)
The way you determine if a 64 integer overflows on a 72 bit machine is
different from how you do it on a 64 bit machine (as in, the code you
write is different). If you want to just do it one way, it is helpful
if you have int64_t, not long long int.

And besides, for intents and purposes, you *DON'T* have C99.
How about creating a big integer library?
Done that. Didn't need fixed size ints. Next question.
Well, then I certain don't need your big integer library.

No, of course you don't. But I'm fine with it, thanks.
I have no
interest in any big integer library that isn't aware precisely the
details of its base integer type its written on top of.

I use unsigned char, so I know I have at least 8 bits to play with in each
element of the array - which is plenty, thanks.
Oh, LOL! Ok, so you have functional support that's useful for
integers sized maybe a few hundred bits. My needs are a little
different (I want to replace GMP in practical applications because its
not thread safe, and I was to be able to scale via lockless
primitives.)
[...] Anyone who
has written an *OPTIMIZED* big integer library should know the serious
performance impact this has.

Last time I measured its performance was about four years ago (when it
managed to do in just-about-zero-time a task that took five hours on
someone else's bignum. (It's okay, we straightened out why his was taking
so much time).
You wrote code that's not worse than the worst thing out there,
therefore its good enough? Well I also agree that insertion sort is
better than bubble sort, but ...
[...] I didn't write it for performance, mind you - I wrote it
for fun, trying to make the code as clear as possible - but it has always
been fast *enough* for any purpose I've found for it.
I'm trying to think of a use for less-than-36-bit primes, and failing.
Factoring maybe?

Maybe. Not terribly convinced that the four bits of game are worth the
portability candle.
You are missing my point. Its not the 4 bits *above* 32 that are the
problem, its the 4 bits *BELOW* 40 that are the problem. If you feed
a 36 bit algorithm with a 40 bit value, then it might not function
correctly.

The point is that not having a precise idea of your integer types
means you can fail in *every* direction. Having precise integer types
just makes so many issues go away.

--
Paul Hsieh
http://www.pobox.com/~qed/
http://bstring.sf.net/
Jan 19 '08 #46

P: n/a
Richard Heathfield wrote:
Paul Hsieh said:
>You have to select the type. (Specifically you cannot select Z(2**64)
from just the operations you use -- you have to *declare* a 64 bit
type.)

If you have C99, you can do that, using long long int. (And if like me you
don't, you can't guarantee that a 64-bit type is available.)
So you ignore native 64 bit types if they are available? You don't have
to have C99 to get 64 bit types.

--
Ian Collins.
Jan 19 '08 #47

P: n/a
Ian Collins said:
Richard Heathfield wrote:
>Paul Hsieh said:
>>You have to select the type. (Specifically you cannot select Z(2**64)
from just the operations you use -- you have to *declare* a 64 bit
type.)

If you have C99, you can do that, using long long int. (And if like me
you don't, you can't guarantee that a 64-bit type is available.)
So you ignore native 64 bit types if they are available?
If I'm writing portable code, yes, I do. It makes life so much simpler.
You don't have to have C99 to get 64 bit types.
Right. C places no upper limits on integer widths, and one Cray system came
within a hair's breadth of having 64-bit chars.

Let me ask you something - do you ignore 1024 bit types if they are
available? How about ignoring 131072 bit types if they are available? What
about 1048576 bit types?

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
Jan 19 '08 #48

P: n/a
Richard Heathfield wrote:
Ian Collins said:
>Richard Heathfield wrote:
>>Paul Hsieh said:

You have to select the type. (Specifically you cannot select Z(2**64)
from just the operations you use -- you have to *declare* a 64 bit
type.)
If you have C99, you can do that, using long long int. (And if like me
you don't, you can't guarantee that a 64-bit type is available.)
So you ignore native 64 bit types if they are available?

If I'm writing portable code, yes, I do. It makes life so much simpler.
I guess that depends if performance is one of your design criteria.
>You don't have to have C99 to get 64 bit types.

Let me ask you something - do you ignore 1024 bit types if they are
available? How about ignoring 131072 bit types if they are available? What
about 1048576 bit types?
Well the platforms I work on are either POSIX compliant, or I use a
POSIX wrapper over the native API, which provides stdint.h.

My approach (shared by a number of opensource projects, libgd for
example) is to test for 64 bit types and use them at configuration or
build time if they are there.

Once systems with larger sizes become available and I have cause to use
them, I'll extend the tests to cover them. So the answer is no.

--
Ian Collins.
Jan 19 '08 #49

P: n/a
On Fri, 18 Jan 2008 11:29:48 +0000, Richard Heathfield
<rj*@see.sig.invalidwrote in comp.lang.c:
Flash Gordon said:
Malcolm McLean wrote, On 18/01/08 09:09:

<snip>
Yes, we're rapidly going down the path of destroying the C basic integer
types.
Note that this is an opinion that seems to be almost unique to Malcolm.
A lot of what Malcolm disagrees with was part of the original standard
published in 1989 so he has a very strange idea of "rapidly".

Here at least, I can agree with you.
Note that some others think the fixed width types are a mistake,
although some of us disagree, there being arguments on both side. More
people (I think) would have liked things like int32_t being the fast
types and having int_exact or int_fixed for the optional fixed sized
types.

I would rather not have seen these types at all, since they seem to me to
enshrine poor practice. But I recognise that there are some spheres of
programming in which they could prove useful.
Really? Over the years I have seen near infinite (it seems) samples
of code with typedefs for U16, USHORT, and the like, not to mention
the very poorly thought-out ones that Microsoft came up with, which
are tied to a fixed bit size but don't include it in the name. So
now, a machine word on a Win32 machine is a DWORD.
Once you start inventing types like int_fast16_t people will use them,
and the language becomes more and more difficult to read.
In *your* opinion.

I think he has a point. At the very least, it becomes *uglier* to read. C
as it stands, if well-written, is at least a relatively elegant language,
not just technically and syntactically but also visually. All these
stretched-out underscore-infested type names will be a real nuisance when
scanning quickly through unfamiliar code.
The problem many predominately desktop/hosted environment programmers
do not seem to understand how important being able to specify exact
integer types is in system programming and embedded systems, which are
the mainstays of C to this day.

They are not the prettiest integer typedefs I have ever seen, but they
have one overwhelming advantage -- they are in the C standard. So in
the future I won't have to look at someone's code and wonder what
types WORD and SWORD are, because I know what int32_t and uint32_t are
on sight.

ARM sells far more 32-bit cores every year than Intel does, and every
one of them is executing C. Even when their higher level applications
are in C++ or Java, both of them rest on a C framework.

Note I am not accusing anyone in particular of being a "predominately
desktop/hosted environment programmer". It is a general observation,
not aimed at anyone in particular.
<snip>
--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://c-faq.com/
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++
http://www.club.cc.cmu.edu/~ajo/docs/FAQ-acllc.html
Jan 19 '08 #50

130 Replies

This discussion thread is closed

Replies have been disabled for this discussion.