> Java is even more portable than Ada, becuase ....
> .... an int is 32 bits, no matter where one is
> running the program, and that a long is 64 bits no matter where, etc.

Of course.  In C, you write implementations not abstractions.  In Java, if
you use primitive types, you do the same.  (If you want to write an
abstraction in Java, you have to take all the OO baggage, whether you need
it or not.)  If you _need_ a particular implementation, you examine the
specifications of the compiler and hardware (or JVM) to identify the one
you need.  It's good that that Java and the JVM made them all the same in
this department, because many portability bugs are due to C programmers
being either too lazy or to uninformed to do that sort of study.

In Ada, you (mostly) specify abstractions (requirements) and the compiler
ensures that the implementation meets those specifications--if it can't,
it rejects the program.  (And the implementation is usually quite
efficient, even when OO features are involved.)  _IF_ there is actually an
implementation (representation) requirement, you don't have to find it in
the compiler and hardware docs--you just specify it and the compiler tells
you if it's not available.  (Not that there's anything wrong with looking
up during design whether it will be supported.)

> Yes, the size of INTEGER is platform dependent.  Although this can largely
> be worked-around by defining a MY_INTEGER of the desired size, string
> indices and exponents are a portability problem since they have to be
> based on INTEGER.

Have you ever seen an Ada compiler with Integer less than 16 bits?  Have
you ever seen an Ada compiler that's less than ten years old with Integer
less than 32 bits?  How many applications can you name that depend on
exponents or string indices larger than 65 thousand?  How many compilers
can you name that will support such an application?

If your algorithm depends on a type or object having a certain range or
size, you declare the type or object accordingly, and tell your suppliers
you can only accept compilers and hardware that will accept your
declarations.

If your algorithm doesn't _depend_ on the range or size, you still
(generally) specify an abstraction that makes sense.

In many years of programming mostly in Ada, some of it embedded/real-time,
I have never seen a portability problem due to the size or range of any
predefined type--not even in cases where we "should have" specified an
abstraction instead.

However, I _have_ seen a lot of ugly code written to workaround problems
caused by blind adherence to a religious "Thou shalt not use predefined
types."  In other words, specifying an implementation that isn't a
requirement, in the false belief that it's needed for portability.

I have fixed as many bugs by removing code that was unnecessary as I have
by adding or modifying code to comply with true requirements.