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. A much more complete list is maintained by the Gnulib project (see Gnulib), covering Current POSIX Functions in Gnulib, Legacy Functions in Gnulib, and Glibc Functions in Gnulib. Please help us keep the Gnulib list as complete as possible.
exitOn ancient hosts, exit returned int.
This is because exit predates void, and there was a long
tradition of it returning int.
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.
mallocThe C standard says a successful 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 (see Particular Function Checks).
putenvPOSIX 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.
reallocIt is problematic to call realloc with a zero size.
The C standard says realloc (NULL, 0) is equivalent to
malloc (0), which means one cannot portably tell whether the call
has succeeded if it returns a null pointer. If ptr is non-null,
the C standard says realloc (ptr, 0) has undefined behavior.
The AC_FUNC_REALLOC macro avoids some of these portability issues.
See Particular Function Checks.
signal handlerIn most cases, it is more robust to use sigaction when it is
available, rather than signal.
snprintfIn C99 and later, 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, notably Microsoft Windows before
Visual Studio 2015 and Windows 10, do not null-terminate the output
and return −1 instead.
Portable code can check the return value of snprintf (buf, sizeof
buf, ...): if the value is negative or is not less than sizeof
buf, an error occurred and the contents of buf can be ignored.
Alternatively, one of the Gnulib modules related to snprintf can
be used. See Gnulib.
strerror_rPOSIX specifies that strerror_r returns an int, but many
systems (e.g., the GNU C Library) provide a
different version returning a char *. AC_FUNC_STRERROR_R
can detect which is in use (see Particular Function Checks).
strnlenAndroid 5.0’s strnlen was broken, because it assumed the addressed array
always had at least the specified number of bytes. For example,
strnlen ("", SIZE_MAX) should return 0 but on Android 5.0 it
crashed.
AIX 4.3 provided a broken version which produces the following results:
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
sysconf_SC_PAGESIZE is standard, but some older systems (e.g., HP-UX
9) have _SC_PAGE_SIZE instead. This can be tested with
#ifdef.
unlinkThe 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.
unsetenvOn MinGW, unsetenv is not available, but a variable ‘FOO’
can be removed with a call putenv ("FOO="), as described under
putenv above.
va_copyC99 and later provide 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_listva_list is not necessarily just a pointer. It can be a
struct, which means NULL is not portable.
Or it can be an array, which means as a function parameter it can be
effectively call-by-reference and library routines might modify the
value back in the caller.
>>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 a few platforms
(e.g., Cray C by default) zero bits are shifted in, the same as a shift of an
unsigned type.
/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.