[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
5.7 Calling System Functions
C implementations differ substantially. Standard C reduces but does not eliminate the incompatibilities; meanwhile, many GNU packages still support pre-standard compilers because this is not hard to do. This chapter gives recommendations for how to use the more-or-less standard C library functions to avoid unnecessary loss of portability.
-
Don't use the return value of
sprintf
. It returns the number of characters written on some systems, but not on all systems. -
Be aware that
vfprintf
is not always available. -
main
should be declared to return typeint
. It should terminate either by callingexit
or by returning the integer status code; make sure it cannot ever return an undefined value. -
Don't declare system functions explicitly.
Almost any declaration for a system function is wrong on some system. To minimize conflicts, leave it to the system header files to declare system functions. If the headers don't declare a function, let it remain undeclared.
While it may seem unclean to use a function without declaring it, in practice this works fine for most system library functions on the systems where this really happens; thus, the disadvantage is only theoretical. By contrast, actual declarations have frequently caused actual conflicts.
- If you must declare a system function, don't specify the argument types. Use an old-style declaration, not a Standard C prototype. The more you specify about the function, the more likely a conflict.
-
In particular, don't unconditionally declare
malloc
orrealloc
.Most GNU programs use those functions just once, in functions conventionally named
xmalloc
andxrealloc
. These functions callmalloc
andrealloc
, respectively, and check the results.Because
xmalloc
andxrealloc
are defined in your program, you can declare them in other files without any risk of type conflict.On most systems,
int
is the same length as a pointer; thus, the calls tomalloc
andrealloc
work fine. For the few exceptional systems (mostly 64-bit machines), you can use conditionalized declarations ofmalloc
andrealloc
—or put these declarations in configuration files specific to those systems. - The string functions require special treatment. Some Unix systems have a header file ‘string.h’; others have ‘strings.h’. Neither file name is portable. There are two things you can do: use Autoconf to figure out which file to include, or don't include either file.
-
If you don't include either strings file, you can't get declarations for
the string functions from the header file in the usual way.
That causes less of a problem than you might think. The newer standard string functions should be avoided anyway because many systems still don't support them. The string functions you can use are these:
strcpy strncpy strcat strncat strlen strcmp strncmp strchr strrchr
The copy and concatenate functions work fine without a declaration as long as you don't use their values. Using their values without a declaration fails on systems where the width of a pointer differs from the width of
int
, and perhaps in other cases. It is trivial to avoid using their values, so do that.The compare functions and
strlen
work fine without a declaration on most systems, possibly all the ones that GNU software runs on. You may find it necessary to declare them conditionally on a few systems.The search functions must be declared to return
char *
. Luckily, there is no variation in the data type they return. But there is variation in their names. Some systems give these functions the namesindex
andrindex
; other systems use the namesstrchr
andstrrchr
. Some systems support both pairs of names, but neither pair works on all systems.You should pick a single pair of names and use it throughout your program. (Nowadays, it is better to choose
strchr
andstrrchr
for new programs, since those are the standard names.) Declare both of those names as functions returningchar *
. On systems which don't support those names, define them as macros in terms of the other pair. For example, here is what to put at the beginning of your file (or in a header) if you want to use the namesstrchr
andstrrchr
throughout:#ifndef HAVE_STRCHR #define strchr index #endif #ifndef HAVE_STRRCHR #define strrchr rindex #endif char *strchr (); char *strrchr ();
Here we assume that HAVE_STRCHR
and HAVE_STRRCHR
are
macros defined in systems where the corresponding functions exist.
One way to get them properly defined is to use Autoconf.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |