Sizes of Integer Types

A

Al Balmer

Really? So uint8_t exists on a machine with 64-bit char and short and int
and long? No, it doesn't. Continuing...

I give up. There's no point to discussing an issue with someone who
argues by quoting half-sentences. You ran out of rational points long
ago, and are just playing. I have better things to do.
 
K

Keith Thompson

Kelsey Bjarnason said:
Kelsey said:
[snips]
On Sun, 16 Sep 2007 12:52:26 -0700, Keith Thompson wrote:
How many people here have said that they'd use the new typedefs in the
right circumstances?

So far, a couple who _also_ note they'd only do this on implementations
where they knew, ahead of time, exact-sized types of the right size
already exist (thus largely negating the utility of said types in the
first place) and myself (and perhaps another one or two) who have pointed
out that had such types actually been made useful, we'd use 'em.

They can only be useful on a platform that supports them. Code that
requires fixed size types is also only useful on a platform that
supports them. The two go hand in hand.

Why is it so barking difficult for some folks to grasp that there is a
difference between "needs" and "would benefit from"?

Code which *needs* fixed-sized types may only work on implementations
where such sizes exist natively.

Code which could _benefit from_ such types could run anywhere such types
existed - even if not native to the system.

ISTR I've said this now about six times.

Yes, of course there's a difference between "needs" and "would benefit
from".

In the following, I'll limit the discussion to 32-bit unsigned types.

Code that *needs* a 32-bit unsigned type can use uint32_t; it will
fail to compile under an implementation that doesn't support it.
That's likely to be a fairly narrow set of programs (something that's
been explicitly acknowledged more times than I care to count), but
those programs can work on a fairly wide set of implementations. The
existence of uint32_t makes it easier to write such code. (Yes, it's
a convenience, nothing more; it benefits some subset of programmers at
a small cost to implementers).

Code that doesn't need an exact 32-bit unsigned type wouldn't use
uint32_t. It can use uint_least32_t, which is guaranteed to exist; it
will be exactly 32 bits whenever that's directly supported, and more
than 32 bits where it isn't.

I think your point in the above is to advocate requiring uint32_t to
be supported by *all* implementations, by emulation if necessary, even
if none of the predefined unsigned types happen to be exactly 32 bits.
This could probably be implemented without *too* much difficulty for
platforms where 32 is an integer multiple of CHAR_BIT. For platforms
where, for example, CHAR_BIT==9, I'm not even sure how you'd define
the semantics; I think you'd have to weaken the requirements for
uint32_t, to the detriment of code that depends on it.

(It might be feasible if CHAR_BIT were required to be a power of 2 no
greater than 32, but getting that change through the standard process
would not be easy. And since you'd probably want to require uint8_t
as well, the upshot is that you'd have to require CHAR_BIT==8. Good
luck getting the DSP manufacturers to approve that.)

And this would benefit *only* code that (a) absolutely requires an
exact 32-bit unsigned type and (b) must run (even if slowly) on
implementations that don't directly support such a type.

Such code is practically nonexistent today, because there's no support
for it. I agree that the benefit to programmers could be non-zero,
but in my opinion it wouldn't be worth the added complication to the
language. (Dropping the wording about when uint32_t must be supported
would be a small simplification, but specifying the semantics would be
non-trivial.)

And most code that needs uint32_t isn't even *intended* to run on such
systems.

I find the existing specification to be a good compromise. Supporting
the typedefs where the underlying types already exist has substantial
benefit for *some* code at very little cost to implementers. Forcing
support for all implementations would be a large burden on
implementers with, I think, very little benefit to programmers.

You've already expressed a willingness to write non-portable code that
assumes unsigned int is exactly 32 bits. What's wrong with allowing
you to make that code work on all implementations where *some*
predefined type is exactly 32 bits?
 
C

Charlie Gordon

Al Balmer said:
My point is that computers are used to do other things than
arithmetic. Masking a 16-bit register to 8 bits does not make it an
8-bit register.

What exactly do you call a register? I don't the C standard can help in
dealing with CPU registers or memory mapped I/O registers...

If your implementation gives you adequate control over these, and uint8_t
and uint16_t types are fit for this purpose, no problem.

But for implementing algorithms that require 2s-complement exact size 8, 16,
32 or 64 bits, it would be helpful if the Standard mandated the support of
the corresponding types. The commitee decided it was not helpful enough to
balance the extra work needed for weird platforms, so be it.

I don't quite agree with them, they did mandate long long, and floating
point arithmetics for all conforming platforms, that's more work than
supporting 2s complement 8/16/32 bits arithmetics on the rare if not
inexistent architectures that don't support it already.

I personally regret that it is not possible in C to describe actual data
structures stored in files with more precision. I would want to tell the
compiler about endianness, alignment and representation and have it generate
the best code for the target architecture. Code that deals with memory
mapped files, device driver I/O space, Graphics chips, would be so much more
readable.
 
C

Charlie Gordon

Al Balmer said:
Unless you have the stdint types. That's what we're talking about.

No that is not sufficient.
say you have a struct { uint16_t x, y } s; there is no guarantee that
accessing s.x will be done with a 16 bit bus read, especially if s.y is also
accessed in the same expression, the compiler is entitled to load 32 bits in
a register and then perform the appropriate bit masking and shifting in
registers to evaluate the expression. A more compelling example is this:

uint32_t read_32bits_le(uint8_t *p) {
return p[0] + (p[1]<<8) + (p[2]<<16) + ((uint32_t)p[3]<<24);
}

The compiler is entitled to produce optimized code that loads a 32 bit word
and return it directly on little endian architectures or bswapped on big
endian machines.

the uintXX_t types do not buy you what you want, you need extra support from
the compiler or at least volatile keywords.
There are many wonders in the world of embedded computing.

It should be easy to name a few then.
 

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