www.delorie.com/gnu/docs/GNU/standards_28.html   search  
Buy GNU books!

GNU Coding Standards

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

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

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

  webmaster   donations   bookstore     delorie software   privacy  
  Copyright 2003   by The Free Software Foundation     Updated Jun 2003