Sizes of Integer Types

R

Richard Heathfield

Chris Hills said:
Richard Heathfield said:
Chris Hills said:
[snips]

On Thu, 06 Sep 2007 11:51:57 -0700, Keith Thompson wrote:

If you just want integer types of specified sizes, take a look at
the <stdint.h> header, which defines int8_t, int16_t, etc.

My copy of the draft says
Your copy of the draft is irrelevant.

It is a DRAFT if you are going to mess around with the compiler you
need the standard itself. NOT a draft.

Is it your contention that the final Standard differs from the draft
in this regard?

No. Just that the draft is just that and there are changes between the
draft and the standard. When you are quoting chapter and verse
anything other than the standard has no validity.
Specifically, Kelsey said: "My copy of the draft says that
intN_t types are optional, an implementation is not required to
provide them." As far as I'm aware,

So you are not certain then?

Are you certain that the Standard says implementations are required to
provide intN_t types? Chapter and verse, please.

So it's ok to quote chapter and verse and be pedantic but use a draft
not the proper standard?

Is that a claim that the final Standard disagrees with the draft in the
matter of whether implementations are required to provide intN_t types?
Don't ever go to court or they will throw you out with logic like that

Hmm. Document 1 says X about Y. Document 2 says X about Y. Your claim
appears to be that, because Kelsey is using Document 1 instead of
Document 2 when reasoning about Y, his argument falls. You call this
logical?
 
K

Kelsey Bjarnason

[snips]

Nonsense, I wouldn't call PPC or SPARC "close equivalents" to x86.

The code will work as intended on a system with, oh, 32 bit chars?
Whoops, nope. As I said, it'll work on an x86 and a few close equivalents.
If your code requires exact size types that can't be defined for a
particular system, it can't be run on that system without rework,
whether the typedefs exist or not.

My code would often be considerably more efficient - space-wise, at least
- if I knew the sizes involved. Algorithmically, it can be considerably
more efficient (and maintainable) if I know the sizes involved.

No more masking to ensure there's only 8 value bits (or 16, or 32) in use.
No more sucking up 32 bits where an 8 bit value is wanted. Even if these
types incurred a speed overhead by emulating the types, chances are it
would be worth it.

Enter uint8_t. Perfect. Just what the doctor ordered. Let's use it.
Except we can't, because it isn't even required to exist.

Oh, sure, there's the alternative - uintleast8_t or whatever. It's
written "unsigned char". Difference is, you write it the new way, the
code won't compile, you write it the old way, the code works.

Yeah, big improvement, these new types.
 
K

Kelsey Bjarnason

[snips]

The lack of portability is imposed by the requirement to use a type
that's exactly 32 bits.

Which means you've already limited your compiler choice, which means you
already know the sizes involved which means _at most_ using a typedef of
your own to achieve exactly what's needed - 32 bit ints on this one, 32
bit longs on that one. The new int types are simply not needed here.

So, we're agreed, in this case, the int types are a complete waste of
paper. Yet this is, apparently, the only time you can rely on them. So
we're agreed; they're useless.
One more time, code that uses uint32_t cannot be 100% portable.

Because uint32_t et al are broken beyond redemption and must be avoided at
all costs. Yes, we're agreed.
But
it's more portable than *your* code that assumes unsigned int is exactly
32 bits, or another version of your code that assumes unsigned long is
exactly 32 bits.

Use a typedef; it's pretty trivial and people have been doing it for what,
30 years?

Oh, I see. The new int types are intended to accomplish something already
done by long practice, but accomplish it in such a way that code relying
on the new approach falls on its face just because you change platforms,
is that what you're saying? No thanks, I'll stick with what works - and
the new int types ain't it.
 
K

Kelsey Bjarnason

[snips]

Consider the following two implementations:

Integer type | SizeA | SizeB
char | 8 | 8
short | 16 | 16
int | 32 | 16
long | 64 | 32

Both implementations have a 32-bit integer type, but they're called different
things. Using int32_t does all the pesky #ifdefing for you.

Now add in a new one:
Integer type | SizeA | SizeB | SizeC
char | 8 | 8 | 64
short | 16 | 16 | 64
int | 32 | 16 | 64
long | 64 | 32 | 64

Voila. Your code falls on its face. Mine keeps right on working, it just
consumes more memory (or stores fewer positions in its tables) due to the
overhead.

Hmm. I win. My code's running, yours needs porting. Yes, and the value
of these new int type was... er... oh, right, the benefit was the jump I
get over my competition, because I chose to do things in a manner that
works, they chose to go with the new stuff that doesn't.

Sounds good to me. Please, feel free to make as much use of the new int
types as you can.

Oh, of course, you _could_ have used intleast8_t and the like. So could
I. In fact I did; they're called "char" and "short" and "int" and "long".
 
K

Kelsey Bjarnason

[snips]

No. Just that the draft is just that and there are changes between the
draft and the standard. When you are quoting chapter and verse anything
other than the standard has no validity.

No freakin' kidding. Why do you think I *stated* *explicitly* that it was
being quoted from the draft, rather than claiming it was from the standard
itself? Maybe, perhaps, just *could be* I recognize the possibility it
could have changed between draft and final? Maybe? Possibly?
 
B

Ben Pfaff

Kelsey Bjarnason said:
Maybe I can use, oh, uintleast8_t or whatever it is, so that even if
the type ends up being 32 bits, it is _at least_ the 8 I need? Hmm...
so's a char, and a short's at least 16 and a long's at least 32. So I'm
better off to just pretend these new int types don't exist at all, because
I simply *cannot* rely on them.

The point of the types with "least" in their names is not to be
"at least" those sizes. It is to be the narrowest (least width)
type with at least that size. int_least16_t is different from
short in that short could be 32 bits on a machine that has a
16-bit char, but int_least16_t would be char on that machine.
 
A

Al Balmer

Ian Collins said:


No, you write the code so as not to need them. In other words, you write
your code *not* to rely on exact size.

Kelsey is absolutely right. If a type isn't guaranteed to be provided by
the implementation, one cannot use it in code that is required to be
portable to arbitrary implementations.

Fortunately, my code never has to be ported to arbitrary
implementations. A dozen or so will suffice :)
 
J

jacob navia

Kelsey said:
[snips]

Consider the following two implementations:

Integer type | SizeA | SizeB
char | 8 | 8
short | 16 | 16
int | 32 | 16
long | 64 | 32

Both implementations have a 32-bit integer type, but they're called different
things. Using int32_t does all the pesky #ifdefing for you.

Now add in a new one:
Integer type | SizeA | SizeB | SizeC
char | 8 | 8 | 64
short | 16 | 16 | 64
int | 32 | 16 | 64
long | 64 | 32 | 64

Voila. Your code falls on its face. Mine keeps right on working, it just
consumes more memory (or stores fewer positions in its tables) due to the
overhead.

Hmm. I win. My code's running, yours needs porting. Yes, and the value
of these new int type was... er... oh, right, the benefit was the jump I
get over my competition, because I chose to do things in a manner that
works, they chose to go with the new stuff that doesn't.

Sounds good to me. Please, feel free to make as much use of the new int
types as you can.

Oh, of course, you _could_ have used intleast8_t and the like. So could
I. In fact I did; they're called "char" and "short" and "int" and "long".

Great!

Now, can you name a platform where sizeof char is 64 bits???

Thanks
 
A

Al Balmer

What you will be doing is reading and writing those values to the
file or i/o system. If the peripheral or file only handles 32 bit
wide values, it will just ignore the higher order bits.

Not necessarily true, and especially for memory-mapped I/O.
 
B

Bart van Ingen Schenau

Kelsey said:
[snips]

You're still missing the point. If I want to write code that is only
portable to systems that have a 32-bit integer type, then the easiest
way to get that data type is to use int32_t.


Which deals with one type. You can, of course, guarantee that this
system
_also_ has, oh, 8 bit integer types, right? No? So all that code
using uint8_t now has to be scrapped or rewritten, because the types
simply aren't available.


No. It is not an all-or-nothing proposition.
If I need a type with exactly 32 bits somewhere in a program, I use
int32_t *at that location*. For all other variables that don't
require an exact width, I use the regular types (or the int_{fast
least}N_t types).

If I need exact-width types of 8, 16 and 32 bits, then either I am doing
something wrong, or my program in inherently non-portable.
By the time you get to the point where all these new types make sense,
you've essentially restricted C to existing only on 32-bit x86
machines or
close equivalents. Hardly sensible.

Except that uint8_t does not need to exist if I only needed a 32-bit
exact width type. So my program is still portable to platforms that do
provide 32-bit integers, but not 8-bit integers.
Nor can you rely on the new types, as they may well simply not exist
on
a given implementation. Yes, and?

If you used the exact-width types correctly (i.e. only when least-width
is not good enough), then you find out at compile-time that your
program can not be ported to that platform without major
rethinking/rework.

If you stuck to the existing types, at best you had found out with a
code review. More likely during testing and at worst only after
delivery of the system to your customers.

One area where the exact-width types can be beneficial, IMHO, is in the
implementation of protocol stacks, where the protocol definition is
octet oriented.
If your target platform does not have an 8-bit data type, you will have
to jump through a lot of complicated hoops to implement the protocol
correctly (where the hoops may depend on the width of the types that
you do have). Adding all these hoops to your implementation while there
is no need for them (all targeted platform support an 8-bit type) will
only increase your development cost and decrease performance.

Bart v Ingen Schenau
 
C

Chris Hills

Richard Heathfield said:
Chris Hills said:
Richard Heathfield said:
Chris Hills said:

[snips]

On Thu, 06 Sep 2007 11:51:57 -0700, Keith Thompson wrote:

If you just want integer types of specified sizes, take a look at
the <stdint.h> header, which defines int8_t, int16_t, etc.

My copy of the draft says
Your copy of the draft is irrelevant.

It is a DRAFT if you are going to mess around with the compiler you
need the standard itself. NOT a draft.

Is it your contention that the final Standard differs from the draft
in this regard?

No. Just that the draft is just that and there are changes between the
draft and the standard. When you are quoting chapter and verse
anything other than the standard has no validity.
Specifically, Kelsey said: "My copy of the draft says that
intN_t types are optional, an implementation is not required to
provide them." As far as I'm aware,

So you are not certain then?

Are you certain that the Standard says implementations are required to
provide intN_t types?

No. I have no idea. What does the standard say (not the draft)
Chapter and verse, please.

You tell me what the STAndard (NOT A DRAFT ) says
Is that a claim that the final Standard disagrees with the draft in the
matter of whether implementations are required to provide intN_t types?

No. But the standard *may* be different to the draft at any given
point. The only way you can know is by checking the standard. The draft
is meaningless.

Not having the standard is because it is expensive is not an acceptable
reason. If you want to work in the industry you have to buy/make* the
correct tools.
Hmm. Document 1 says X about Y. Document 2 says X about Y. Your claim
appears to be that, because Kelsey is using Document 1 instead of
Document 2 when reasoning about Y, his argument falls. You call this
logical?

As some one involved in 2 ISO, 1 IEC and and other international
standard I can tell you that you only work from released standards.
quoting from arbitrary drafts is pointless and has no validity.


*
I make several of the standard I use. Others I buy. Some are expensive.
So are some tools and test suites. That is the same in any industry.

How would you feel if a surgeon was operating on you using a draft
procedure rather than the certified procedure because the certified one
costs money?
 
C

Chris Hills

Kelsey Bjarnason said:
[snips]

No. Just that the draft is just that and there are changes between the
draft and the standard. When you are quoting chapter and verse anything
other than the standard has no validity.

No freakin' kidding. Why do you think I *stated* *explicitly* that it was
being quoted from the draft, rather than claiming it was from the standard
itself? Maybe, perhaps, just *could be* I recognize the possibility it
could have changed between draft and final? Maybe? Possibly?

Then why quote form a document that may or may not be correct. There is
no value in that.

Either use the standard or don't. Don't use something that may or may
not be right but tries to pretend it has some authority.
 
B

Bart van Ingen Schenau

Kelsey said:
[snips]

If it doesn't exist, it's because the implementation doesn't have a
predefined 32-bit unsigned type.

Making the use of the type effectively impossible, as you can no long
expect your code to compile, on a conforming compiler, except by
accident. Not a great leap forward for C portability.
If you're writing code intended to be maximally portable, then you
don't want or need a type that's exactly 32 bits.

Don't _need_ one, perhaps. Want is another matter. For example, take
a chess program; it would be very nice to specify an 8-bit type for
some purposes, a 32-bit type for others and a 64-bit for some other
purposes.

You don't *need* exact-sized types, of course. If char, int and long
are all 32 bits, you may end up wasting a good whack of space in
storing transition tables and the like but the program will still
work... it's just rather likely to work somewhat less efficiently as
the storage overhead skyrockets.

As the code does not require an exact width, you *don't use* the types
uint8_t, uint32_t and uint64_t. Instead you use the more appropriate
uint_least8_t, uint_least32_t and uint_least64_t.

Then you can even port the program to a processor that has 8-bit char,
64-bit short, 128-bit int, 256-bit long and 512-bit long long without
wasting too much space.
Try doing that without using typedefs.

Because unlike that abortion, I can rely on *my* typedefs actually
existing.

Then please show us your typedef for a type of *exactly* 32 bits on a
system with 9-bit char, 18-bit short, 36-bit int and long and 72-bit
long long.
But why go out of your way to limit its portability, by adopting
things
which simply will not exist?

It is not me who restricted the portability. It is the guy who wrote
down the requirements for the software I am making that restricted the
portability by requiring the use of an exact-width type.
It is not my fault that System Z can't fulfil the preconditions needed
for using the software.

Do you also complain that the device driver for a token-ring network
adapter is not portable to systems that can't interface with such a
device?

Bart v Ingen Schenau
 
K

Keith Thompson

Richard Heathfield said:
No, you write the code so as not to need them. In other words, you write
your code *not* to rely on exact size.

Ideally, yes.
Kelsey is absolutely right. If a type isn't guaranteed to be provided by
the implementation, one cannot use it in code that is required to be
portable to arbitrary implementations.

And if that were all Kelsey had said, I would agree completely.

But he's also saying that *because* the exact-width types aren't 100%
portable, they're completely useless. I disagree. They can be useful
in some contexts; those contexts do not allow for portability to
arbitrary implementations. Sometimes portability to all
implementations that support *some* 32-bit integer type is good enough
-- and better than portability to all implementations where int is 32
bits, or to all implementations where long is 32 bits.
 
K

Keith Thompson

Richard Heathfield said:
Ian Collins said:
Richard said:
So one must exercise care even in C90 (or accept that one's code is
not portable to certain kinds of implementation). C99 has all of the
C90 portability issues, and adds a whole bunch of new ones.
But availability of fixed wi[d]th types isn't one of them,

It *is*, if people are lured into using C99's named types unnecessarily,
because they (erroneously) believe that this somehow makes their code
more portable than is in fact the case.

Certainly any programmer should understand just what uint32_t is
before using it. As I've said before, it would have made a lot more
sense to call it uint_exact32_t; the simple name it has now just makes
it too tempting to use where it's not really needed.

*But* I think that having (optional) exact-width types is a good idea,
for those fairly rare cases where that happens to be exactly what you
need.
 
K

Keith Thompson

Kelsey Bjarnason said:
[snips]
Consider the following two implementations:

Integer type | SizeA | SizeB
char | 8 | 8
short | 16 | 16
int | 32 | 16
long | 64 | 32

Both implementations have a 32-bit integer type, but they're called
different things. Using int32_t does all the pesky #ifdefing for
you.

Now add in a new one:
Integer type | SizeA | SizeB | SizeC
char | 8 | 8 | 64
short | 16 | 16 | 64
int | 32 | 16 | 64
long | 64 | 32 | 64

Voila. Your code falls on its face. Mine keeps right on working, it just
consumes more memory (or stores fewer positions in its tables) due to the
overhead.

Hmm. I win. My code's running, yours needs porting. Yes, and the value
of these new int type was... er... oh, right, the benefit was the jump I
get over my competition, because I chose to do things in a manner that
works, they chose to go with the new stuff that doesn't.

Once again, the assumption is that there's a pre-existing requirement
for an unsigned integer type that's *exactly* 32 bits wide. Given
that requirement, your code will fail on system C, because the
implementation cannot meet the requirement, but the failure may be
subtle because your code still compiles. Philip's code also fails,
but it does so with a compile-time error because 'uint32_t' doesn't
exist.

You're assuming that you need a type that's *at least* 32 bits. In
that case, using uint32_t would be wrong, and *nobody is suggesting
otherwise*.
Sounds good to me. Please, feel free to make as much use of the new int
types as you can.

No, I'll use them as much as I need to.
Oh, of course, you _could_ have used intleast8_t and the like. So could
I. In fact I did; they're called "char" and "short" and "int" and "long".

They aren't the same thing. Which of char, short, int, and long is
guaranteed to be the *smallest* predefined type that's at least 32
bits?

If you only care about having a width of at least 32 bits, and you
don't mind wasting some space, you can use long. If you want at least
32 bits while wasting as little space as possible, you can use
uint_least32_t. You're free to use either approach.

And if you never need a type that's exactly 32 bits wide, then you
should never use uint32_t. But you might consider allowing it for
those who occasionally really do need something that's exactly 32 bits
wide (and are willing to live with the loss of portability).

(I'm being sloppy about signed vs. unsigned types here, but I think
the point is clear enough anyway.)
 
K

Keith Thompson

jacob navia said:
Kelsey said:
[snips]
Integer type | SizeA | SizeB | SizeC
char | 8 | 8 | 64
short | 16 | 16 | 64
int | 32 | 16 | 64
long | 64 | 32 | 64
[...]
Great!

Now, can you name a platform where sizeof char is 64 bits???

No, I can't, though such a platform is possible. (I've heard of
platforms, namely DSPs, with 32-bit char; a 64-bit DSP is entirely
plausible.)

But I've actually used systems with 8-bit char, 64-bit short, 64-bit
int, and 64-bit long, which makes the point equaly well.
 
K

Keith Thompson

Kelsey Bjarnason said:
[snips]
The lack of portability is imposed by the requirement to use a type
that's exactly 32 bits.

Which means you've already limited your compiler choice, which means you
already know the sizes involved which means _at most_ using a typedef of
your own to achieve exactly what's needed - 32 bit ints on this one, 32
bit longs on that one. The new int types are simply not needed here.

No, they're not absolutely needed, but they can be useful in some
limited contexts.
So, we're agreed, in this case, the int types are a complete waste of
paper. Yet this is, apparently, the only time you can rely on them. So
we're agreed; they're useless.


Because uint32_t et al are broken beyond redemption and must be avoided at
all costs. Yes, we're agreed.

Do *not* put words in my mouth.

Are you asserting that anything that's not 100% portable is useless?
Really?
Use a typedef; it's pretty trivial and people have been doing it for what,
30 years?

Ok, show me how to write a typedef for a signed type that's exactly 32
bits wide, with no padding bits and a 2's-complement representation,
so that I don't have to change the definition for different platforms.

Oh, wait, somebody's already done that for you; it's called uint32_t.
Oh, I see. The new int types are intended to accomplish something already
done by long practice, but accomplish it in such a way that code relying
on the new approach falls on its face just because you change platforms,
is that what you're saying? No thanks, I'll stick with what works - and
the new int types ain't it.

Good for you. Write your own code any way you like.

Listen carefully. Nobody has claimed that the uintN_t types are 100%
portable; they clearly are not. Repeatedly pointing out that they're
not 100% portable, as if you were refuting something, is useless.

If *you* don't need a type that's *exactly* 32 bits wide, then *you*
definitely shouldn't use uint32_t. Happy?
 
F

Flash Gordon

Richard Heathfield wrote, On 12/09/07 10:19:
Ian Collins said:
Richard said:
So one must exercise care even in C90 (or accept that one's code is
not portable to certain kinds of implementation). C99 has all of the
C90 portability issues, and adds a whole bunch of new ones.
But availability of fixed wi[d]th types isn't one of them,

It *is*, if people are lured into using C99's named types unnecessarily,
because they (erroneously) believe that this somehow makes their code
more portable than is in fact the case.

If you know the portability limitations of exact width types then using
them makes your code portable to exactly the correct extent.
...but not a huge one - certainly not huge enough to justify C99's
muddying the waters of portability.

Others obviously disagree.
...which don't actually perform any useful function that I can see.

It makes it simple to make code that relies on exact width types to be
portable to all the implementations it is required to be portable to and
guarantees that it will fail to compile on implementations it is
definitely not portable to. This is a very useful property.
Indeed. The first choice is a natural one, but has its limitations, as
we have already seen. The second choice is a harder road, but it is
unavoidable if maximal portability is a prerequisite.

Maximal portability is not always a requirement. Sometimes portability
to a specific range of machines is sufficient, and fixed width types
make providing that degree of portability and ensuring that people are
not mislead by the application compiling where it will not work easy.
 
R

Richard Heathfield

Chris Hills said:
Richard said:
Chris Hills said:
[snips]

On Thu, 06 Sep 2007 11:51:57 -0700, Keith Thompson wrote:

If you just want integer types of specified sizes, take a look
at the <stdint.h> header, which defines int8_t, int16_t, etc.

My copy of the draft says
Your copy of the draft is irrelevant.

It is a DRAFT if you are going to mess around with the compiler
you need the standard itself. NOT a draft.

Is it your contention that the final Standard differs from the draft
in this regard?

No. Just that the draft is just that and there are changes between
the draft and the standard. When you are quoting chapter and verse
anything other than the standard has no validity.

Specifically, Kelsey said: "My copy of the draft says that
intN_t types are optional, an implementation is not required to
provide them." As far as I'm aware,

So you are not certain then?

Are you certain that the Standard says implementations are required to
provide intN_t types?

No. I have no idea. What does the standard say (not the draft)

It says:

"These types are optional."

Compare and contrast with the draft, which says:

"These types are optional."
You tell me what the STAndard (NOT A DRAFT ) says

Since you ask what the Standard says, am I to presume that you only have
a draft? Anyway, it says "These types are optional." Just like the
draft.

[...] But the standard *may* be different to the draft at any given
point.

It isn't different at this point.
The only way you can know is by checking the standard. The
draft is meaningless.

Two things that are equal to the same thing are equal to each other. *In
this respect*, the Standard is equal to the draft. If what the draft
says about the optional nature of intN_t types is meaningless, then
what the Standard says about the optional nature of intN_t types is
also meaningless.
Not having the standard is because it is expensive is not an
acceptable reason.

You're preaching to the choir. I bought a copy of the C99 Standard as
soon as it came out.

How would you feel if a surgeon was operating on you using a draft
procedure rather than the certified procedure because the certified
one costs money?

It would depend on whether the draft procedure was exactly the same as
the certified procedure. If there is no difference between them, it is
silly to argue that one is superior to the other.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top