PCC compatibility mode


This section discusses the differences apparent when the compiler is used in PCC mode. When given the -pcc command line flag, the C compiler will accept (Berkeley) Unix-compatible C, as defined by the implementation of the Portable C Compiler and subject to the restrictions which are noted below.

In essence, PCC-style C is K&R C, as defined by B. Kernighan and D. Ritchie in their book The C Programming Language, together with a small number of extensions, and some clarifications of language features that the book leaves undefined.

Language and preprocessor compatibility

In -pcc mode, the ARM C compiler accepts K&R C, but it does not accept many of pcc's old-style compatibility features, the use of which has been deprecated and warned against for years. The differences are:

This is accepted by some Unix PCCs and may cause problems when porting old (and badly written) code:

With the exception of enums, the compiler's type checking is generally stricter than PCC, much more akin to lint's, in fact. In writing the ARM C compiler, we have attempted to strike a balance between giving too many warnings when compiling known, working code, and warning of poor or non portable programming practices. Many PCCs silently compile code which has no chance of executing in just a slightly different environment. We have tried to be helpful to those who need to port C among machines in which the following varies:

The compiler's preprocessor is believed to be equivalent to a BSD Unix cpp except for the points listed below. Unfortunately, cpp is only defined by its implementation, and although equivalence has been tested over a large body of Unix source code, completely identical behaviour cannot be guaranteed. Some of the points listed below only apply when the -E option is used with the cc command:

Standard headers and libraries

Use of the compiler in -pcc mode precludes neither the use of the standard ANSI headers built in to the compiler nor the use of the run-time library supplied with the C compiler. Of course, the ANSI library does not contain the whole of the Unix C library, but it does contain many commonly used functions. However, look out for functions with different names, or a slightly different definition, or those in different standard places. Unless the user directs otherwise using -j, the C compiler will attempt to satisfy references to, say, stdio.h from its built-in filing system.

Listed below are a number of differences between the ANSI C Library, and the BSD Unix library. They are placed under headings corresponding to the ANSI header files:

ctype.h

There are no isascii() and toascii() functions, since ANSI C is not character-set specific.

errno.h

On BSD systems sys_nerr and sys_errlist() are defined to give error messages corresponding to error numbers. ANSI C does not have these, but provides similar functionality via perror(const char *s), which displays the string pointed to by s followed by a system error message corresponding to the current value of errno.

There is also char *strerror(int errnum) which, when given a purported value of errno, returns its textual equivalent.

math.h

The #defined value HUGE, found in BSD libraries, is called HUGE_VAL in ANSI C. ANSI C does not have asinh(), acosh() or atanh().

signal.h

In ANSI C the signal() function's prototype is:

extern void (*signal(int, void(*func)(int)))(int);

signal() therefore expects its second argument to be a pointer to a function returning void with one int argument. In BSD-style programs it is common to use a function returning int as a signal handler. The PCC-style function definitions shown below will therefore produce a compiler warning about an implicit cast between different function pointers (since f() defaults to int f()). This is just a warning, and correct code will be generated anyway.

f(signo)
int signo;
...
main()
{   extern f();
    signal(SIGINT, f);
...

stdio.h

sprintf() returns the number of characters printed (following Unix System V), whereas the BSD's sprintf() returns a pointer to the start of the character buffer.

The BSD functions ecvt(), fcvt() and gcvt() are not included in ANSI C, since their functionality is provided by sprintf().

string.h

On BSD systems, string manipulation functions are found in strings.h whereas ANSI C places them in string.h. The ARM C Compiler also recognises strings.h, for PCC-compatibility.

The BSD functions index() and rindex() are replaced by the ANSI functions strchr() and strrchr() respectively.

Functions which refer to string lengths (and other sizes) now use the ANSI type size_t, which in our implementation is unsigned int.

stdlib.h

malloc() has type void *, rather than the char * of the BSD malloc().

float.h

A new header added by ANSI giving details of floating point precision etc.

limits.h

A new header added by ANSI to give maximum and minimum limit values for integer data types.

locale.h

A new header added by ANSI to provide local environment-specific features.