On Sun, May 26, 2002 at 06:46:39PM -0700, Joe Malone wrote:
> In the original edition of K&R's "The C Programming Language", int is
> described as "an integer, typically reflecting the natural size of
> integers on the host machine."  Examples are given for machines upon
> which an int is 16, 32, and 36 bits.  In contrast, I think you can
> expect a UInt16 to be 16 bits, regardless of the machine you use to
> compile your code.

Right.  A name like "UInt16" says, to those in the know, that it's an
unsigned integral type of exactly 16 bits.  Meanwhile, "unsigned int"
just means (in practice, at least) the machine's most efficient
("natural") unsigned integral type of at least 16 bits (coincidentally
enough).

(Somewhat tangentially, I think the "new" (SDK 3.5 and later) names are
better than the old ones:  I for one could never remember whether "Word"
was supposed to be unsigned or not.  So I supported the fact that they
were changed, although the specific change was not what I would have
liked.)

So using a name like "UInt16" provides more information:  it specifies
the size exactly.  The question is whether having that information is
always important.

And Tom Frauenhofer <[EMAIL PROTECTED]> wrote:
> [...] The type "int" is another matter, this is a
> fault of the C standard (given its original definition as the native word
> size on the computer).  Given the change to the ARM processor [...]
> When you consider portability then the arguments against
> C's definition of int are very compelling.

On the contrary:  when I consider portability, I find a compelling
argument that having that information is not merely unimportant, but
positively damaging!

Very little code really *needs* to know *exactly* how big its datatypes
are [1].  The only kind of code that does really need it is things like
structure packing and unpacking, and it is possible to write even that
portably, without assuming the sizes of your ints etc, by explicitly
moving individual chars (a.k.a. bytes) around.

Of course such code can be made to go faster, e.g., on m68k we can use
UInt16 and friends and move larger items around.  But such code is
actually *less* portable: to make it work on different architectures,
you have to know things like what alignment your types will need and
what endianness they will have.  So such code is then m68k-only code
anyway, so you could have just written "unsigned short" with a comment
saying "on m68k, this is 16 bits".  All the typedefs really give you,
given that such code is m68k-only, is a common vocabulary, so it's
easier for other programmers to read (well, other Palm OS programmers
anyway).  (Of course, that common vocabulary is useful in itself, but
read on.)

Even the system API functions don't really need to specify this in such
detail: for example, the Unix API has got by with API functions defined
in terms of "int" rather than some specifically sized type for decades.
The ABI on each platform specifies what "int" means and lots else
besides, so if you have two compilers for some (32-bit) platform, they
will agree on how to call "wait (int *)" and will both pass a pointer to
the right sized thing.  Sure wait() on that weird 36-bit machine might
expect a different sized thing, but that's okay because programs
compiled for each platform aren't expected to run on the other one
(different machine language!), so you won't be mixing calls to different
waits().  Properly written source code using "int" will compile to
32-bit ints on one, and 36-bit ints on the other, and not care.  In
fact, if the Unix API said "wait (Int32 *)" it might not even be
implementable on that 36-bit platform (which might not have a type of
exactly 32 bits)!  How would that make the API more portable?

IMHO emphasising the exact sizes of your ints is often emphasising an
irrelevant detail and can lead to an overly low level view of what
you're trying to accomplish.  And programming in high level languages is
often said to be desirable :-).

Now let's look at why using types like Int16 can even be *damaging*.
First off, that 36-bit machine might not even have a viable exactly 16
bit type, but let's ignore that because we probably don't want to port
our code to such a weird machine that's probably dying off anyway.

What about ARM?  We probably care about porting our code to ARM.  In my
opinion, using types like "Int16" instead of "int" makes your code
*harder* to port well from m68k to ARM.

The reason is that ARM does not have an efficient 16 bit integral
datatype [2].  C code using 16 bit types is actually going to run
*slower* and be larger than the same code using 32 bit types:  because
it's only got 32 bit arithmetic instructions, the CPU's going to spend
half its time masking off the top half of registers before it can do
arithmetic on them.

The point is that UInt16 ("give me exactly 16 bits, whatever the
consequences") is overconstraining the problem.  Most of the time
(certainly for local variables in registers, perhaps not for data
structures in memory), what you really want to say is "give me something
reasonably efficient that's at least 16 bits", and that's what C's
classic native types like "short", "int", "long", etc, give you.

Interestingly, C99 added a bunch of [U]Int16-like types, and it was
pretty controversial.  Lots of people thought adding them was just
pandering to a need that wasn't really there, for the reasons I've been
trying to explain.  But they went a lot further:  C99's <stdint.h>
(section 7.18 of the Standard) defines

  [u]intN_t             native type of exactly N bits
        ("These types are optional.  However if an implementation
        provides integer types with widths of 8, 16, 32, or 64 bits,
        it shall define the corresponding typedef names".  And you can
        supply others too: e.g. that weird machine could have int36_t)

  [u]int_leastN_t       smallest native type of at least N bits
  [u]int_fastN_t        "fastest" native type of at least N bits
        (N = 8,16,32,64 must all be provided)

  [u]intmax_t           the biggest native type you've got

and there's all kinds of other things in there, including macros to tell
you what exists.

Me, I was horrified when I heard that C9X was adding this rubbish.  But
now, even though I don't expect to use them much myself, I quite like
them:  I think the three different kinds allow you to specify what you
Really Want quite well, much better than just [u]intN_t alone does, and
the common vocabulary will be useful.  Instead of every project defining
its own uint16/uword/word/UInt16/ushort/u_short variation and having to
look each one up in each project's headers to check what it really is,
we'll have a familiar standardized vocabulary.

Kenneth Albanowski and I joined Palm when the 3.5 SDK was in
development.  When we heard that the type names were being changed we
said great, and then we looked at each other dumbfounded and said "huh?
how come they're not using the C9X names?".  But we were meek little new
hires, and didn't kick up a fuss.

For a long time I regretted not arguing for the standardised C9X types.
But eventually I realised it would have been a waste of energy.  The aim
of the new names wasn't just to have a common vocabulary with all the
other C programmers in the world; the new names also had to conform to
someone's Coding Standard.

It's an improvement over Word et al, but it could have been so much
better :-(.  (And it's all mostly unnecessary anyway :-).)


Well, I hope some of that was interesting.  It wasn't intended as mere
posturing.  Really.  So, Mark, even if you don't agree with it, have you
now heard a compelling technical argument for the way C's primitive
types are?

    John

[1] Most does need to know that its datatypes are "at least this big",
    e.g., it needs some range guarantee such as that int can hold at
    least -32767 to +32767, and C's native data types have given you
    that kind of assurance for at least 10 years.

[2] Unless you're using a 5E or higher ARM architecture?  I have no idea
    which cores have that, but I'm guessing it's not the ones that are
    interesting for handhelds.

-- 
For information on using the Palm Developer Forums, or to unsubscribe, please see 
http://www.palmos.com/dev/support/forums/

Reply via email to