(autoconf.info)Function Portability

Next: Particular Functions Up: Library Functions

5.5.1 Portability of C Functions

Most usual functions can either be missing, or be buggy, or be limited
on some architectures.  This section tries to make an inventory of these
portability issues.  By definition, this list always requires
additions.  Please help us keeping it as complete as possible.

     On ancient hosts, `exit' returned `int'.  This is because `exit'
     predates `void', and there was a long tradition of it returning

     On current hosts, the problem more likely is that `exit' is not
     declared, due to C++ problems of some sort or another.  For this
     reason we suggest that test programs not invoke `exit', but return
     from `main' instead.

     The C standard says a call `free (NULL)' does nothing, but some
     old systems don't support this (e.g., NextStep).

     The C99 standard says that `isinf' and `isnan' are macros.  On
     some systems just macros are available (e.g., HP-UX and Solaris
     10), on some systems both macros and functions (e.g., glibc
     2.3.2), and on some systems only functions (e.g., IRIX 6 and
     Solaris 9).  In some cases these functions are declared in
     nonstandard headers like `<sunmath.h>' and defined in non-default
     libraries like `-lm' or `-lsunmath'.

     The C99 `isinf' and `isnan' macros work correctly with `long
     double' arguments, but pre-C99 systems that use functions
     typically assume `double' arguments.  On such a system, `isinf'
     incorrectly returns true for a finite `long double' argument that
     is outside the range of `double'.

     To work around this porting mess, you can use code like the

          #include <math.h>

          #ifndef isnan
          # define isnan(x) \
              (sizeof (x) == sizeof (long double) ? isnan_ld (x) \
               : sizeof (x) == sizeof (double) ? isnan_d (x) \
               : isnan_f (x))
          static inline int isnan_f  (float       x) { return x != x; }
          static inline int isnan_d  (double      x) { return x != x; }
          static inline int isnan_ld (long double x) { return x != x; }

          #ifndef isinf
          # define isinf(x) \
              (sizeof (x) == sizeof (long double) ? isinf_ld (x) \
               : sizeof (x) == sizeof (double) ? isinf_d (x) \
               : isinf_f (x))
          static inline int isinf_f  (float       x) { return isnan (x - x); }
          static inline int isinf_d  (double      x) { return isnan (x - x); }
          static inline int isinf_ld (long double x) { return isnan (x - x); }

     Use `AC_C_INLINE' (Note: C Compiler) so that this code works on
     compilers that lack the `inline' keyword.  Some optimizing
     compilers mishandle these definitions, but systems with that bug
     typically have missing or broken `isnan' functions anyway, so it's
     probably not worth worrying about.

     The C standard says a call `malloc (0)' is implementation
     dependent.  It can return either `NULL' or a new non-null pointer.
     The latter is more common (e.g., the GNU C Library) but is by no
     means universal.  `AC_FUNC_MALLOC' can be used to insist on
     non-`NULL' (Note: Particular Functions).

     Posix prefers `setenv' to `putenv'; among other things, `putenv'
     is not required of all Posix implementations, but `setenv' is.

     Posix specifies that `putenv' puts the given string directly in
     `environ', but some systems make a copy of it instead (e.g., glibc
     2.0, or BSD).  And when a copy is made, `unsetenv' might not free
     it, causing a memory leak (e.g., FreeBSD 4).

     On some systems `putenv ("FOO")' removes `FOO' from the
     environment, but this is not standard usage and it dumps core on
     some systems (e.g., AIX).

     On MinGW, a call `putenv ("FOO=")' removes `FOO' from the
     environment, rather than inserting it with an empty value.

     The C standard says a call `realloc (NULL, size)' is equivalent to
     `malloc (size)', but some old systems don't support this (e.g.,

`signal' handler
     Normally `signal' takes a handler function with a return type of
     `void', but some old systems required `int' instead.  Any actual
     `int' value returned is not used; this is only a difference in the
     function prototype demanded.

     All systems we know of in current use return `void'.  The `int'
     was to support K&R C, where of course `void' is not available.
     `AC_TYPE_SIGNAL' (Note: Particular Types) can be used to
     establish the correct type in all cases.

     The C99 standard says that if the output array isn't big enough
     and if no other errors occur, `snprintf' and `vsnprintf' truncate
     the output and return the number of bytes that ought to have been
     produced.  Some older systems return the truncated length (e.g.,
     GNU C Library 2.0.x or IRIX 6.5), some a negative value (e.g.,
     earlier GNU C Library versions), and some the buffer length
     without truncation (e.g., 32-bit Solaris 7).  Also, some buggy
     older systems ignore the length and overrun the buffer (e.g.,
     64-bit Solaris 7).

     The C standard says `sprintf' and `vsprintf' return the number of
     bytes written.  On some ancient systems (SunOS 4 for instance)
     they return the buffer pointer instead, but these no longer need
     to be worried about.

     On various old systems, e.g., HP-UX 9, `sscanf' requires that its
     input string be writable (though it doesn't actually change it).
     This can be a problem when using `gcc' since it normally puts
     constant strings in read-only memory (Note: Incompatibilities of
     GCC.).  Apparently in some cases even
     having format strings read-only can be a problem.

     Posix specifies that `strerror_r' returns an `int', but many
     systems (e.g., GNU C Library version 2.2.4) provide a different
     version returning a `char *'.  `AC_FUNC_STRERROR_R' can detect
     which is in use (Note: Particular Functions).

     AIX 4.3 provides a broken version which produces the following

          strnlen ("foobar", 0) = 0
          strnlen ("foobar", 1) = 3
          strnlen ("foobar", 2) = 2
          strnlen ("foobar", 3) = 1
          strnlen ("foobar", 4) = 0
          strnlen ("foobar", 5) = 6
          strnlen ("foobar", 6) = 6
          strnlen ("foobar", 7) = 6
          strnlen ("foobar", 8) = 6
          strnlen ("foobar", 9) = 6

     `_SC_PAGESIZE' is standard, but some older systems (e.g., HP-UX 9)
     have `_SC_PAGE_SIZE' instead.  This can be tested with `#ifdef'.

     The Posix spec says that `unlink' causes the given file to be
     removed only after there are no more open file handles for it.
     Some non-Posix hosts have trouble with this requirement, though,
     and some DOS variants even corrupt the file system.

     On MinGW, `unsetenv' is not available, but a variable `FOO' can be
     removed with a call `putenv ("FOO=")', as described under `putenv'

     The C99 standard provides `va_copy' for copying `va_list'
     variables.  It may be available in older environments too, though
     possibly as `__va_copy' (e.g., `gcc' in strict pre-C99 mode).
     These can be tested with `#ifdef'.  A fallback to `memcpy (&dst,
     &src, sizeof (va_list))' gives maximum portability.

     `va_list' is not necessarily just a pointer.  It can be a `struct'
     (e.g., `gcc' on Alpha), which means `NULL' is not portable.  Or it
     can be an array (e.g., `gcc' in some PowerPC configurations),
     which means as a function parameter it can be effectively
     call-by-reference and library routines might modify the value back
     in the caller (e.g., `vsnprintf' in the GNU C Library 2.1).

Signed `>>'
     Normally the C `>>' right shift of a signed type replicates the
     high bit, giving a so-called "arithmetic" shift.  But care should
     be taken since Standard C doesn't require that behavior.  On those
     few processors without a native arithmetic shift (for instance Cray
     vector systems) zero bits may be shifted in, the same as a shift
     of an unsigned type.

Integer `/'
     C divides signed integers by truncating their quotient toward zero,
     yielding the same result as Fortran.  However, before C99 the
     standard allowed C implementations to take the floor or ceiling of
     the quotient in some cases.  Hardly any implementations took
     advantage of this freedom, though, and it's probably not worth
     worrying about this issue nowadays.

automatically generated by info2www