GNU Info

Info Node: (standards.info)CPU Portability

(standards.info)CPU Portability


Next: System Functions Prev: System Portability Up: Writing C
Enter node , (file) or (file)node

Portability between CPUs
========================

   Even GNU systems will differ because of differences among CPU
types--for example, difference in byte ordering and alignment
requirements.  It is absolutely essential to handle these differences.
However, don't make any effort to cater to the possibility that an
`int' will be less than 32 bits.  We don't support 16-bit machines in
GNU.

   Similarly, don't make any effort to cater to the possibility that
`long' will be smaller than predefined types like `size_t'.  For
example, the following code is ok:

     printf ("size = %lu\n", (unsigned long) sizeof array);
     printf ("diff = %ld\n", (long) (pointer2 - pointer1));

   1989 Standard C requires this to work, and we know of only one
counterexample: 64-bit programs on Microsoft Windows IA-64.  We will
leave it to those who want to port GNU programs to that environment to
figure out how to do it.

   Predefined file-size types like `off_t' are an exception: they are
longer than `long' on many platforms, so code like the above won't work
with them.  One way to print an `off_t' value portably is to print its
digits yourself, one by one.

   Don't assume that the address of an `int' object is also the address
of its least-significant byte.  This is false on big-endian machines.
Thus, don't make the following mistake:

     int c;
     ...
     while ((c = getchar()) != EOF)
       write(file_descriptor, &c, 1);

   When calling functions, you need not worry about the difference
between pointers of various types, or between pointers and integers.
On most machines, there's no difference anyway.  As for the few
machines where there is a difference, all of them support Standard C
prototypes, so you can use prototypes (perhaps conditionalized to be
active only in Standard C) to make the code work on those systems.

   In certain cases, it is ok to pass integer and pointer arguments
indiscriminately to the same function, and use no prototype on any
system.  For example, many GNU programs have error-reporting functions
that pass their arguments along to `printf' and friends:

     error (s, a1, a2, a3)
          char *s;
          char *a1, *a2, *a3;
     {
       fprintf (stderr, "error: ");
       fprintf (stderr, s, a1, a2, a3);
     }

In practice, this works on all machines, since a pointer is generally
the widest possible kind of argument; it is much simpler than any
"correct" alternative.  Be sure _not_ to use a prototype for such
functions.

   If you have decided to use Standard C, then you can instead define
`error' using `stdarg.h', and pass the arguments along to `vfprintf'.

   Avoid casting pointers to integers if you can.  Such casts greatly
reduce portability, and in most programs they are easy to avoid.  In the
cases where casting pointers to integers is essential--such as, a Lisp
interpreter which stores type information as well as an address in one
word--you'll have to make explicit provisions to handle different word
sizes.  You will also need to make provision for systems in which the
normal range of addresses you can get from `malloc' starts far away
from zero.


automatically generated by info2www version 1.2.2.9