Sizes of Integer Types

H

Harald van =?UTF-8?B?RMSzaw==?=

Kelsey said:
[snips]

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 that intN_t types are optional, an
implementation is not required to provide them. As such, it strikes me
that code cannot rely on them unless one gives up portability across
compilers, never mind OSen.

Has this changed, or is this still little more than a good way to
guarantee you're stuck using one vendor's compiler for the rest of
eternity?

int8_t, int16_t, int32_t, int64_t and the corresponding unsigned integer
types are required on systems where there exist types matching the
descriptions. This means that on C99 implementations where they're not
defined, it wouldn't be possible to use some other type as a substitute
anyway, unless you didn't really need an exact-width integer type in the
first place.
 
F

Flash Gordon

Kelsey Bjarnason wrote, On 10/09/07 17:02:
[snips]

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 that intN_t types are optional, an
implementation is not required to provide them. As such, it strikes me
that code cannot rely on them unless one gives up portability across
compilers, never mind OSen.

Has this changed, or is this still little more than a good way to
guarantee you're stuck using one vendor's compiler for the rest of
eternity?

The relevant section is 1.18.1.1 para 3:
| These types are optional. However, if an implementation provides
integer types with
| widths of 8, 16, 32, or 64 bits, no padding bits, and (for the signed
types) that have a
| two’s complement representation, it shall deï¬ne the corresponding
typedef names.

So if it has a type matching the requirements it has to provide the
relevant typedef.

Personally I think it would be better if it required providing the
intN_t types for all values of N for which it has a type with no
padding bits (and two's complement for the signed versions). I can't see
that it would be much work for the implementer.
 
C

CBFalconer

Flash said:
.... snip ...

Personally I think it would be better if it required providing the
intN_t types for all values of N for which it has a type with
no padding bits (and two's complement for the signed versions). I
can't see that it would be much work for the implementer.


Ugh. You don't really want to hear my opinion about those useless
non-portable foolishnesses.
 
R

Richard Bos

CBFalconer said:
Flash said:
Personally I think it would be better if it required providing the
intN_t types for all values of N for which it has a type with
no padding bits (and two's complement for the signed versions). I
can't see that it would be much work for the implementer.


Ugh. You don't really want to hear my opinion about those useless
non-portable foolishnesses.


Their unportability is, in this case, a feature. Suppose that you want
an exactly 32-bit unsigned type, for example to agree with a file
format. If your C99 implementation has a type of the kind you want, you
can rely on uint32_t being there. If uint32_t is not available, that
implementation is simply never going to give you what you want. In C90,
you'd have to put that kind of type behind conditional compilation
#ifdefs, one for each platform you want, _and_ hope that your compiler
never introduces padding bits behind your back; or you have to surround
every use of your type with &0xFFFFFFFF and so on. In C99, all you have
to do is check whether your compiler complains about uint32_t not
existing.

Richard
 
K

Kelsey Bjarnason

[snips]

Their unportability is, in this case, a feature. Suppose that you want
an exactly 32-bit unsigned type, for example to agree with a file
format. If your C99 implementation has a type of the kind you want, you
can rely on uint32_t being there. If uint32_t is not available, that
implementation is simply never going to give you what you want.

No, but if I were to use, say, an unsigned long I'd know I was using an
unsigned type at least 32 bits long, and more importantly, I'd know the
type was going to exist, period.

So now I use a uint32_t and my code fails on compiler X because the type
simply does not exist.

My options now are twofold: introduce an additional complexity, via ifdefs
and the like, such that on compiler X it uses unsigned long and a lot of
masking, where on compiler Y it uses uint32_t, or I can do the sensible
thing: skip uint32_t entirely and just write the code using standard types
so that it will work anywhere.

At which point, of course, the new integer types become instantly
irrelevant - so why have them?
In C90,
you'd have to put that kind of type behind conditional compilation
#ifdefs, one for each platform you want, _and_ hope that your compiler
never introduces padding bits behind your back; or you have to surround
every use of your type with &0xFFFFFFFF and so on. In C99, all you have
to do is check whether your compiler complains about uint32_t not
existing.

No, not "check whether your compiler complains". You have to write the
code such that it works, correctly, _regardless_ of the compiler - this is
the point to writing portable code, that you don't _care_ what compiler it
is built with, modulo a few minor exceptions (eg requiring a minimum
32-bit implementation).

The fact you cannot do this while using uint32_t et al unless you also
include code to support those implementations which don't have them
increases code complexity for no benefit; the old types and masking, etc,
will work just as well on both so if you have to write that anyway, why
add more code to do the exact same job using the new types?

The new types would be great if you could rely on them. You can't. Since
you can't, they're no more benefit than if they didn't exist at all.
 
S

Stephen Sprunk

Kelsey Bjarnason said:
No, not "check whether your compiler complains". You have to write the
code such that it works, correctly, _regardless_ of the compiler - this is
the point to writing portable code, that you don't _care_ what compiler it
is built with, modulo a few minor exceptions (eg requiring a minimum
32-bit implementation).

The fact you cannot do this while using uint32_t et al unless you also
include code to support those implementations which don't have them
increases code complexity for no benefit; the old types and masking, etc,
will work just as well on both so if you have to write that anyway, why
add more code to do the exact same job using the new types?

This newsgroup notwithstanding, the reality is that there are a lot of
people that choose to write "unportable" code for various purposes. Those
purposes may, for instance, may only include situations where a 32-bit type
is mandatory and a system that provides only 24- and 48-bit (or 36-bit)
types will never be targeted because the code has no purpose _ever_ being
used on those machines. Or the programmer (or her management) may simply
decide that supporting other machines is irrelevant, but code should still
be portable to "common" systems.

Such code is not portable in the purest sense of the word, but "portable to
all 32-bit and 64-bit systems" is sufficient for a lot of code. For
instance, you may have a PCI device you're writing drivers for, and being
portable to every architecture that has PCI implementations is all that
matters. Who cares whether the code runs on a PDP-8 if PCI isn't available
there?

(I'm sure the DS9k will acquire PCI support as a result of this message, and
someone will explain how to cleanly write drivers that will be perfectly
portable to it despite having some oddball number of bits in an int/long,
but come on, folks, this is far past the point where anyone can defend
requiring 100% portable code.)

S
 
K

Keith Thompson

CBFalconer said:
Flash said:
Personally I think it would be better if it required providing the
intN_t types for all values of N for which it has a type with
no padding bits (and two's complement for the signed versions). I
can't see that it would be much work for the implementer.


Ugh. You don't really want to hear my opinion about those useless
non-portable foolishnesses.


Their unportability is, in this case, a feature. Suppose that you want
an exactly 32-bit unsigned type, for example to agree with a file
format. If your C99 implementation has a type of the kind you want, you
can rely on uint32_t being there. If uint32_t is not available, that
implementation is simply never going to give you what you want. In C90,
you'd have to put that kind of type behind conditional compilation
#ifdefs, one for each platform you want, _and_ hope that your compiler
never introduces padding bits behind your back; or you have to surround
every use of your type with &0xFFFFFFFF and so on. In C99, all you have
to do is check whether your compiler complains about uint32_t not
existing.


All you have to do is;

#include <stdint.h>
#ifdef UINT32_MAX
/* uint32_t exists */
#else
/* uint32_t doesn't exist */
#endif

What to do if UINT32_MAX isn't defined depends on the application. If
you don't care about supporting implementations that don't have a
32-bit unsigned integer type, you can use #error to abort the
compilation with whatever error message you like. If you do care
about such implementations, you have some more work to do.
 
A

Al Balmer

[snips]

Their unportability is, in this case, a feature. Suppose that you want
an exactly 32-bit unsigned type, for example to agree with a file
format. If your C99 implementation has a type of the kind you want, you
can rely on uint32_t being there. If uint32_t is not available, that
implementation is simply never going to give you what you want.

No, but if I were to use, say, an unsigned long I'd know I was using an
unsigned type at least 32 bits long, and more importantly, I'd know the
type was going to exist, period.

So now I use a uint32_t and my code fails on compiler X because the type
simply does not exist.

Then, neither does the 32-bit unsigned long. If your requirement is
for a type *at least* 32 bits, rather than exactly 32 bits, you would
use int_least32_t.
 
K

Keith Thompson

Kelsey Bjarnason said:
[snips]

Their unportability is, in this case, a feature. Suppose that you want
an exactly 32-bit unsigned type, for example to agree with a file
format. If your C99 implementation has a type of the kind you want, you
can rely on uint32_t being there. If uint32_t is not available, that
implementation is simply never going to give you what you want.

No, but if I were to use, say, an unsigned long I'd know I was using an
unsigned type at least 32 bits long, and more importantly, I'd know the
type was going to exist, period.

So now I use a uint32_t and my code fails on compiler X because the type
simply does not exist.

Then you shouldn't have used uint32_t.

If you want the smallest unsigned type that's at least 32 bits, you
can use uint_least32_t. If you want the "fastest" unsigned type
that's at least 32 bits, you can use uint_fast32_t. Both are required
to exist -- assuming, of course, that you have either a C99
implementation or a pre-c99 implementation that supports <stdint.h>.

Of course you can just use unsigned long, which is guaranteed to be at
least 32 bits. But if, for example, int is 32 bits and long is 64
bits, and operations on int are faster than operations on long, then
you're wasting both time and space.
My options now are twofold: introduce an additional complexity, via ifdefs
and the like, such that on compiler X it uses unsigned long and a lot of
masking, where on compiler Y it uses uint32_t, or I can do the sensible
thing: skip uint32_t entirely and just write the code using standard types
so that it will work anywhere.

At which point, of course, the new integer types become instantly
irrelevant - so why have them?

The purpose of the exact-width types is to support non-portable code.
If you need to write 100% portable code, don't use them.

[...]
No, not "check whether your compiler complains". You have to write the
code such that it works, correctly, _regardless_ of the compiler - this is
the point to writing portable code, that you don't _care_ what compiler it
is built with, modulo a few minor exceptions (eg requiring a minimum
32-bit implementation).

No, you don't *have* to write code that works corretly regardless of
the compiler. Sometimes it's sufficient to write code that works
correctly for the implementations you care about, and cleanly fails
compilation for implementations where it won't work.

[...]
 
C

CBFalconer

Richard said:
CBFalconer said:
Flash said:
Personally I think it would be better if it required providing the
intN_t types for all values of N for which it has a type with
no padding bits (and two's complement for the signed versions). I
can't see that it would be much work for the implementer.


Ugh. You don't really want to hear my opinion about those useless
non-portable foolishnesses.


Their unportability is, in this case, a feature. Suppose that you want
an exactly 32-bit unsigned type, for example to agree with a file
format. If your C99 implementation has a type of the kind you want, you
can rely on uint32_t being there. If uint32_t is not available, that
implementation is simply never going to give you what you want. In C90,
you'd have to put that kind of type behind conditional compilation
#ifdefs, one for each platform you want, _and_ hope that your compiler
never introduces padding bits behind your back; or you have to surround
every use of your type with &0xFFFFFFFF and so on. In C99, all you have
to do is check whether your compiler complains about uint32_t not
existing.


Lets work with your example. The padding bits don't matter,
because they don't show up in the actual values, they are limited
to catching such things as use of uninitialized data, or ECC error
correction, etc. So we assume the file system is capable of
writing 36 bit values, as a result of having CHAR_BIT == 9 in the
system. But you are writing software using values that have to
work on the usual system with CHAR_BIT == 8. unsigned long always
has at least 32 bits available, so you use that type (or
uint32_t). The padding doesn't matter, as stated above (most
systems with ECC today really have a 72 bit word, which is what is
really being read and written from/to memory).

You have less worries about overflows with the 36 bit system.
Using unsigned values, truncation down to 32 bits doesn't matter,
the truncated result will be identical to the value on the 32 bit
system. But it is generally easier to detect 32 bit overflow with
a 36 bit system. You won't be doing any such.

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. This just
gives the identical result to what would have happened on the 32
bit system. Everything is free!!.

What about input from the device/file? The high order bits will be
zeroed, we assume, because the hardware has some pins tied to
ground, or the equivalent. In comes a value identical the the
value on the 32 bit system. Once more, everything is free.

Notice there has never been any need to mask off fields. Now shoot
me down.
 
K

Kelsey Bjarnason

[snips]

This newsgroup notwithstanding, the reality is that there are a lot of
people that choose to write "unportable" code for various purposes.

Sure, I've done so myself. And when doing so, I'll happily use the fact
that on implementation X, char is 8 bits, int 16, long 32 or what have you
and not need those pesky int32_t things at all.

Remember, they have to exist _if_ the implementation already has such
types, meaning that if they exist, you *already* have perfectly
functional, though non-portable, options, making the int types completely
irrelevant.
Those purposes may, for instance, may only include situations where a
32-bit type is mandatory and a system that provides only 24- and 48-bit
(or 36-bit) types will never be targeted because the code has no purpose
_ever_ being used on those machines.

Possibly, but then again, who are you to say whether the code belongs on
a different architecture - unless you're doing something
architecture-specific.
Or the programmer (or her
management) may simply decide that supporting other machines is
irrelevant, but code should still be portable to "common" systems.

And 640K is enough for anybody. Write the code right, you don't care if
it's run on a 48 bit machine.
Such code is not portable in the purest sense of the word, but "portable
to all 32-bit and 64-bit systems" is sufficient for a lot of code.

And you cannot rely on inttypes on those, as a device which uses 32-bit
types for all is a 32-bit system, but not one providing, oh, a uint8_t
equivalent type, meaning you cannot rely on the inttypes being useful even
on "32 and 64 bit systems", whereas you *can* write code that works on
them... which means once again, the int types are useless.
 
K

Kelsey Bjarnason

[snips]

Their unportability is, in this case, a feature. Suppose that you want
an exactly 32-bit unsigned type, for example to agree with a file
format. If your C99 implementation has a type of the kind you want, you
can rely on uint32_t being there. If uint32_t is not available, that
implementation is simply never going to give you what you want.

No, but if I were to use, say, an unsigned long I'd know I was using an
unsigned type at least 32 bits long, and more importantly, I'd know the
type was going to exist, period.

So now I use a uint32_t and my code fails on compiler X because the type
simply does not exist.

Then, neither does the 32-bit unsigned long. If your requirement is
for a type *at least* 32 bits, rather than exactly 32 bits, you would
use int_least32_t.

Exactly the point. We *already* have, without the new int types, a
functional set of types which are _at least_ n bits wide. With the new
int types, we have... oh, yes, a functional set of types which are _at
least_ n bits wide. Those types? char, short, int, long (and now long
long).

Exactly the same set (apart from the addition of long long). So why have
the new int types? You can't rely on them being there, you can't write
portable code with them.

They have all the utility of void main() - they'll work, somewhere, on some
compiler, for some definition of "work", but you can't rely on them
working _at all_ on an arbitrary compiler.

Stuff like that should be mandated or abolished; left in limbo it detracts
from the language instead of adding to it.
 
K

Kelsey Bjarnason

[snips]

Then you shouldn't have used uint32_t.

Exactly the point - *why* doesn't it exist?

Oh, right, because an implementation *may* have it. Or it may not. Does
it? Your guess is as good as mine - but if I'm writing code intended to
be portable, I can't afford to guess, but I can't tell what compiler might
be used, either.

Simple solution: use types that work. char, short, int, long. Relying on
this half-baked nonsense of types that a conforming implementation can get
away with not including at all is ridiculous.
The purpose of the exact-width types is to support non-portable code. If
you need to write 100% portable code, don't use them.

Lots of things can be made more efficient with known sizes. Except you
can't do that because the types you could use to pull this off can't be
relied on to even exist. As to non-portable code, the new types, as I
read it, only need to exist _if_ the implementation _already_ has existing
equivalent-sized types... so you don't need the new types for this; they
buy nothing.
No, you don't *have* to write code that works corretly regardless of the
compiler.

True; I could write code that needs to be rewritten every time one changes
compilers. Doing so, however, would be costly and pointless. I like to
write things as portably as possible, which is one reason I like C. The
new int types could have been something of a boon in this regard; instead
they're more of a boondoggle. Completely devoid of any value, as far as I
can see.

You could convince me there might be some redeeming value, but you're
going to have to do better than "non-portable code" to pull it off, as
these types are required to exist only where existing types of the right
size exist, AIUI... meaning your non-portable code *already* has the
option to make non-portable use of type sizes, meaning you don't need the
new int types, meaning they're not justified for that purpose... but then,
they can't be relied upon to even exist for other purposes, so convincing
me is going to require showing how you can write code which is neither
portable nor non-portable, that makes use of them in a manner in which
existing types cannot be used.

I don't think it can be done... but then, I'm not the one suggesting these
things have a justification for existing in the first place.
 
S

Stephen Sprunk

Kelsey Bjarnason said:
Lots of things can be made more efficient with known sizes. Except you
can't do that because the types you could use to pull this off can't be
relied on to even exist. As to non-portable code, the new types, as I
read it, only need to exist _if_ the implementation _already_ has existing
equivalent-sized types... so you don't need the new types for this; they
buy nothing.

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. Note that I didn't say an integer
type of "at least" 32 bits, which is what I'd get if I used "long". If I'm
relying on a variable being exactly 32 bits, no more or less, I cannot use a
long for that purpose. Pre-stdint, I had to use a bunch of preprocessor
hacks to typedef a "u32" or error out; now I can just #include <stdint.h>,
declare a variable as uint32_t, and if the code compiles I know I got
exactly what I wanted.

S
 
K

Keith Thompson

Kelsey Bjarnason said:
[snips]

Then you shouldn't have used uint32_t.

Exactly the point - *why* doesn't it exist?

If it doesn't exist, it's because the implementation doesn't have a
predefined 32-bit unsigned type. Maybe it's a 64-bit system with
8-bit bytes and 64-bit shorts (I've used such systems). Maybe it's a
system with 9-bit bytes.
Oh, right, because an implementation *may* have it. Or it may not. Does
it? Your guess is as good as mine - but if I'm writing code intended to
be portable, I can't afford to guess, but I can't tell what compiler might
be used, either.

If you're writing code intended to be maximally portable, then you
don't want or need a type that's exactly 32 bits.
Simple solution: use types that work. char, short, int, long. Relying on
this half-baked nonsense of types that a conforming implementation can get
away with not including at all is ridiculous.


Lots of things can be made more efficient with known sizes. Except you
can't do that because the types you could use to pull this off can't be
relied on to even exist. As to non-portable code, the new types, as I
read it, only need to exist _if_ the implementation _already_ has existing
equivalent-sized types... so you don't need the new types for this; they
buy nothing.

The give you *names* for types of specified widths. (That's all
typedefs do.)
True; I could write code that needs to be rewritten every time one changes
compilers. Doing so, however, would be costly and pointless. I like to
write things as portably as possible, which is one reason I like C. The
new int types could have been something of a boon in this regard; instead
they're more of a boondoggle. Completely devoid of any value, as far as I
can see.

Or you can write code that has requirements that can be met on some,
but not all, implementations, and you can use things like int32_t both
to meet those requirements where it's possible, and to indicate (by a
compilation failure) when it's not.

In another article in this thread, you wrote:
| Sure, I've done so myself. And when doing so, I'll happily use the fact
| that on implementation X, char is 8 bits, int 16, long 32 or what have you
| and not need those pesky int32_t things at all.

Suppose you have an externally imposed requirement for an unsigned
integer type that's exactly 32 bits. Assume three implementations:

System X: int is 16 bits, long is 32 bits
System Y: int is 32 bits, long is 64 bits
System Z: int is 18 bits, long is 36 bits

You can use 'unsigned long', and your program will work only on System
X. Or you can use 'unsigned int', and your program will work only on
System Y. Or you can use 'uint32_t', and your program will work on
*both* System X and System Y.

(Or you can use your own typedef, defined as unsigned long on System X
and unigned int on System Y, but why bother with the authors of
<stdint.h> have already done it for you?)

None of these will work on System Z, of course; that's not the point.
Either you accept the fact that your software isn't 100% portable, or
you do the hard work of emulating 32-bit integers on systems that
don't directly support them. Portability is not a simple binary
state. <stdint.h> can help in writing software that's more portable
that it otherwise would be, without necessarily being 100% portable.
(Assuming, as always, that the implementation provides <stdint.h>.)

In my opinion, making the exact-width types the "default" (i.e., the
types with the most obvious names) was a poor choice. I would have
preferred the optional exact-width 32-bit unsigned type to be called
uint_exact32_t. With the current naming scheme, it's too tempting to
use exact-width types when what's really needed is a "least" or "fast"
type.

But the exact-width types can be useful in some contexts.
 
A

Al Balmer

Exactly the point. We *already* have, without the new int types, a
functional set of types which are _at least_ n bits wide. With the new
int types, we have... oh, yes, a functional set of types which are _at
least_ n bits wide. Those types? char, short, int, long (and now long
long).

They are not guaranteed to be the same size on different platforms,
and sometimes you want exact size.
 
K

Kelsey Bjarnason

They are not guaranteed to be the same size on different platforms,
and sometimes you want exact size.

Indeed. And yet you can't rely on that, because the new int types may not
exist *at all* on the new platform.
 
K

Kelsey Bjarnason

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

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.

Note that I didn't say
an integer type of "at least" 32 bits, which is what I'd get if I used
"long". If I'm relying on a variable being exactly 32 bits, no more or
less, I cannot use a long for that purpose.

Nor can you rely on the new types, as they may well simply not exist on
a given implementation. Yes, and?
 
K

Kelsey Bjarnason

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

Now if that code could actually rely upon the new int types existing, then
it could opt to use them, with the realization that there will be, on some
systems, some overhead in using some of the types, but trading that off
against the inefficiencies of massively increased storage requirements
(or, worse, massively reducing the amount of effective storage used).

Can't do it, though, because those types don't exist. Or, rather, they
do, for compiler X but not Y. Maybe. If it's a Thursday and sufficient
dead chickens have been waved.
The give you *names* for types of specified widths. (That's all
typedefs do.)

Yeah, and you can't rely on 'em, so you have to get all intimate with the
implementation anyways so your code gives up any hope of being portable so
you may as well use the types which _do_ exist. Again, these things buy
nothing.
Or you can write code that has requirements that can be met on some,
but not all, implementations, and you can use things like int32_t both
to meet those requirements where it's possible, and to indicate (by a
compilation failure) when it's not.

Sure. Now how about a case where you'd need to do this? I gave an
example of where having known sized types is beneficial, but lacking them
isn't fatal. How about you give us an example where lacking known sized
types is fatal, but you don't know and can't restrict the used
implementations?

That is, show us a case where you absolutely have to have 32-bit ints,
say, but cannot know and cannot restrict the code to implementations which
support a 32-bit int.

Oh, but wait... if you *can* do this, then you don't need the new int
types anyhow, because the size of a plain old int works just fine and you
don't need these newfangled monstrosities.
(Or you can use your own typedef, defined as unsigned long on System X
and unigned int on System Y, but why bother with the authors of
<stdint.h> have already done it for you?)

Because unlike that abortion, I can rely on *my* typedefs actually
existing.
None of these will work on System Z, of course; that's not the point.
Either you accept the fact that your software isn't 100% portable

But why go out of your way to limit its portability, by adopting things
which simply will not exist? Hey, my C compiler only works if you have a
Token Ring adapter installed! Makes bugger all sense. There's enough
limits and hassles in writing portable code already, without going out of
your way to add on extra limits which don't buy anything.
 
K

Keith Thompson

Kelsey Bjarnason 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.

It's not "by accident". The code will compile on any system that
provides uint32_t. It won't compile on systems that don't provide
uint32_t.

What's your superior alternative, *given* a requirement for 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.

Ok, for "don't need", substitute "can't have".

[...]
Can't do it, though, because those types don't exist. Or, rather, they
do, for compiler X but not Y. Maybe. If it's a Thursday and sufficient
dead chickens have been waved.

uint32_t exists on any implementation that has a 32-bit unsigned type
with no padding bits. Of course that's not *all* implementations, but
these days it happens to be most of them.

[...]
Sure. Now how about a case where you'd need to do this? I gave an
example of where having known sized types is beneficial, but lacking them
isn't fatal. How about you give us an example where lacking known sized
types is fatal, but you don't know and can't restrict the used
implementations?

That is, show us a case where you absolutely have to have 32-bit ints,
say, but cannot know and cannot restrict the code to implementations which
support a 32-bit int.

If you absolutely have to have 32-bit *integers*, why should you have
to restrict your code to implementations where *int* is 32 bits? With
uint32_t, it doesn't matter whether the 32-bit unsigned type is
unsigned int, unsigned short, or unsigned long.
Oh, but wait... if you *can* do this, then you don't need the new int
types anyhow, because the size of a plain old int works just fine and you
don't need these newfangled monstrosities.

Sure, if you want to restrict yourself to implementations where int is
32 bits, go ahead. I'd rather restrict myself to the larger set of
implementations where *some* integer type is 32 bits.
Because unlike that abortion, I can rely on *my* typedefs actually
existing.

No, you can't, at least not if your typedefs are intended to have
the same meaning.

The assumption, once again, is that you require an unsigned integer
type that's exactly 32 bits. If the implementation doesn't provide
such a type, you can't define your own typedef for it, any more
than <stdint.h> could do so.

And if you don't require a type that's exactly 32 bits, then *you
don't use uint32_t*.
But why go out of your way to limit its portability, by adopting things
which simply will not exist? Hey, my C compiler only works if you have a
Token Ring adapter installed! Makes bugger all sense. There's enough
limits and hassles in writing portable code already, without going out of
your way to add on extra limits which don't buy anything.

The lack of portability is imposed by the requirement to use a type
that's exactly 32 bits. (Such requirements do exist; no, I don't have
an example.) Providing uint32_t doesn't change that. It just gives
you a way to meet the requirement when it's possible to do so.

One more time, code that uses uint32_t cannot be 100% portable. 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.

And once again, if you don't need exact-width integer types, nobody
will require you to use them.
 

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

Forum statistics

Threads
473,744
Messages
2,569,483
Members
44,902
Latest member
Elena68X5

Latest Threads

Top