This document gives a brief summary of additions made to the
C programming language by the
Draft Proposed C Standard (X3J11/85-044),
which was released by
the American National Standards Institute (ANSI)
for public review on April 30, 1985.
The Draft Standard extends and slightly modifies the language described by
Kernighan and Ritchie in
.IR "The C Programming Language" ,
(Prentice-Hall, 1978).
The proposed changes to the language may break some existing code.
The
.MP portability
manual page summarizes
those changes which will most likely affect programmers who are
currently using the C compiler
.SC cc .
The additions to C, however, overcome some of the deficiencies
which currently plague the language.
Except where noted below, all of these new features are supported by \*n.
.SH "Additions to C"
.SS "Prototypes:"
The most useful addition to the language in the Draft Standard is
the prototype.
A prototype is a function declaration that specifies the type
of the parameters as well as the result type.
Here are some examples of prototypes:
@(E
	/* 'strlen' is a function which returns an int */
	/* and takes one parameter of type pointer to */
	/* char. */
	int strlen(char *);

	/* 'main' is a function which returns nothing */
	/* and takes an int and the address of an array */
	/* of pointers to a char. */
	void main(int argc, char *argv[]);

	/* 'handler' is a function returning a pointer */
	/* to a function which takes an int and returns */
	/* nothing.  'handle' takes two parameters. */
	/* The first is an int.  The second is a pointer */
	/* to a function which takes an int and returns */
	/* nothing. */
	void (*handler(int sig, void (*func)(int)))(int);
@)E
.PP
The formal parameter names given in a prototype declaration are optional.
A function may be defined using a prototype, in which case,
of course, the parameter names must be specified.
The storage class
.KW register
is allowed in the parameter declarations.
Using the prototype format,
.EX strlen
might be defined as:
@(E
	int strlen(register char *str)
	{
		register int i = 0;
		while(*str++) i++;
		return i;
	}
@)E
.PP
If a function takes a variable number of arguments,
then an ellipsis is used after the last specified parameter.
For example, the prototype for
.EX printf
reads as follows:
@(E
	/* 'printf' is a function which returns an */
	/* int and takes one parameter of type */
	/* pointer to char and zero or more other */
	/* parameters of unspecified type. */
	int printf(char *format, ...);
@)E
' .PP
' See the
' .I varargs
' manual page for more details on
' functions taking a variable number of arguments.
' .PP
The advantage of the function prototype is that
it permits load-time checking of
the types of the actual parameters being passed to a function.
(Note that \*n also performs run-time checking.)
@(E
	1 -> \*uextern int printf(char *, ...) ; \*p
	2 -> \*uprintf(1) ;\*p /* Draws a warning. */
@)E
In addition, the \*(AN specifies that
when a prototype for a function is in scope
the standard automatic conversions are performed on the arguments
passed to that function.
In the following example,
the integer value 100 is converted to double before being passed to
the function
.EX sqrt .
@(E
	1 -> \*uextern double sqrt(double) ;\*p
	2 -> \*usqrt(100) ;\*p /* 100 is converted to 100.0 */
@)E
Prototypes are very useful since they facilitate type checking,
but the automatic conversion performed on the arguments can be
annoying since in is not compatible with
.SC cc .
For this reason, the
.FL ansi
option is provided.
Automatic conversion of arguments passed to a function declared
with a prototype only occurs when the
.FL ansi
option is set.
If this option is not set, then no conversion will occur
and a warning will be generated issued when the
call to the function is seen.
@(E
	1 -> /* Turn automatic conversion on */
	2 -> \*usetopt("ansi") ;\*p
	3 -> \*udouble inc(double d) { return d + 1.0; }\*p
	4 -> \*uinc(3) ;\*p /* 3 is converted to 3.0 */
	(double) 4.000000e+00
	5 -> /* Turn automatic conversion off */
	6 -> \*uunsetopt("ansi") ;\*p
	7 -> \*uinc(3) ;\*p /* 3 is not converted. */
	/* Parameter type mismatch warning. */
@)E
To ensure backwards compatibility with
.SC cc ,
the
.FL ansi
option is unset by default.
.SS "Signed Types:"
The keyword
.KW signed
has been added to the language.
.KW Signed
is the opposite of
.KW unsigned ,
and it may be used just like
.KW unsigned
to modify any of the integral types
.KW char ,
.KW short ,
.KW int ,
and
.KW long .
If the type is
.KW short ,
.KW int ,
or
.KW long ,
and neither
.KW signed
or
.KW unsigned
is specified,
then the type defaults to being signed.
If, however, the type is
.KW char ,
and neither
.KW signed
or
.KW unsigned
is specified,
then whether the type is signed or unsigned
is implementation defined.
The main consequence of all of this is that since some machines
automatically sign extended chars and others do not,
the only way to guarantee one behavior or the other is to explicitly
use
.KW "signed char"
where sign extension must be performed
and
.KW "unsigned char"
where sign extension must not be performed.
Otherwise, the implementation will do whatever is most efficient
for the host machine.
.PP
A third floating point type,
.KW "long double" ,
has been created.
Just as a
.KW double
is something at least as long as a
.KW float ,
a
.KW "long double"
is something at least as long as a
.KW double .
The use of
.KW "long float"
as a synonym for
.KW double
has been discarded.
In summary, there are now 11 predefined types in C:
@(E
	signed char		unsigned char		float
	signed short	unsigned short		double
	signed int		unsigned int		long double
	signed long		unsigned long
@)E
.SS "Constants:"
For each of the
.KW int
and
.KW long
types
and for all of the floating point types
there is now a corresponding constant format.
Also, for character constants and string literals,
hexadecimal values may be in escape sequences.
Here are some examples of the different types of arithmetic constants
and escape sequences now allowed:
@(E
	/* Constants with type signed int. */
	255			0xff		0XFF		0377

	/* Constants with type unsigned int. */
	255U		0xFFu		0377U		0x00ffu

	/* Constants with type signed long. */
	255L		255l		0xffl		000377L

	/* Constants with type unsigned long. */
	255UL		255lu		0xffLu		0377Ul

	/* Constants with type double */
	255.0		0.0255E4	.255e+3		25500E-2

	/* Constants with type float. */
	255.0f		0.0255E4F	.255e+3f	25500E-2F

	/* Constants with type long double. */
	255.0L		0.0255E4l	.255E+3L	25500e-2l

	/* Octal and hexadecimal escape sequences in */
	/* string literals and character constants. */
	"\e377"		'\e377'		"\exff"		'\exFF'
@)E
.SS "Const and Volatile:"
Two new type attributes,
.KW const
and
.KW volatile ,
have been added to the language.
.KW Volatile
specifies that the value of an expression may change in unpredictable ways.
The most important use of
.KW volatile
is to tell the compiler not to perform certain types of optimizations.
This is especially useful for data that may be modified asynchronously,
such as occurs with signals.
Consider the following functions which perform a loop until an interrupt
occurs.
@(E
	int interrupt_flag = FALSE;

	void do_signal()
	{
		interrupt_flag = TRUE;
	}

	do_loop()
	{
		/* Loop exits when an interrupt occurs. */
		signal(SIGINT, do_signal);
		for( ; ; )
		{
			/* Some actions ... */
			if(interrupt_flag) return;
			/* Some more actions ... */
		}
	}
@)E
Since the value of
.EX interrupt_flag
does not appear to change inside the
.KW for -loop,
an optimizing compiler may rearrange the second function as if it read:
@(E
	do_loop()
	{
		signal(SIGINT, do_signal);
		if(interrupt_flag) return;
		for( ; ; )
		{
			/* Some actions ... */
		}
	}
@)E
To prevent this from happening the declaration of
.EX interrupt_flag
should be changed to:
@(E
	volatile int interrupt_flag = FALSE;
@)E
An expression with a
.KW const
type cannot be an lvalue, that is, it cannot be modified.
For example, a string literal, according to the Draft Standard,
is an array of
.KW "const char" .
The
.KW const
attribute may be used to guarantee that data is not inadvertently changed.
The prototype for
.EX strlen
might more correctly be given as:
@(E
	int strlen(const char *);
@)E
This guarantees that
.EX strlen
examines, but does not change, the string addressed by its parameter.
Static objects which are
.KW const
but not
.KW volatile ,
such as string literals,
may be placed in read-only memory.
.SS "Unary plus:"
A unary plus operator has been added to C.
Even though the unary plus operator simply
returns the value of its sole operand,
expressions involving unary plus must be evaluated as
if the operation had a real effect.
The main purpose of the unary plus operator to prevent an optimizing
compiler from rearranging sub-expressions, since,
especially for floating pointer operations,
this may affect the precession of the result.
.SS "Preprocessor:"
Several additions have been made to the C preprocessor.
There is now a
.PD elif
directive, which is a combination of the
.PD else
and
.PD if
directives.
Consider the following sequence of preprocessor directives:
@(E
	#if FOO == FUM
		/* Here if FOO == FUM */
	#else
	#if FOO == FEE
		/* Here if FOO != FUM and FOO == FEE */
	#else
		/* Here if FOO != FUM and FOO != FEE */
	#endif
	#endif
@)E
Using
.PD elif
this example can be written more concisely as:
@(E
	#if FOO == FUM
		/* Here if FOO == FUM */
	#elif FOO == FEE
		/* Here if FOO != FUM and FOO == FEE */
	#else
		/* Here if FOO != FUM and FOO != FEE */
	#endif
@)E
.PP
In
.PD if
directives, expressions of the form
@(E
	defined MACRO_NAME
@)E
or
@(E
	defined ( MACRO_NAME )
@)E
may appear.
The expressions evaluates to 1 if macro
.I MACRO_NAME
is currently defined, or 0 if it is not.
The
.PD defined
operator effectively makes the
.PD ifdef
and
.PD ifndef
directives obsolete, because
@(E
	#ifdef MACRO_NAME
@)E
and
@(E
	#ifndef MACRO_NAME
@)E
may now be written as:
@(E
	#if defined(MACRO_NAME)
@)E
and
@(E
	#if !defined(MACRO_NAME)
@)E
The parentheses are optional.
.PP
Some changes have been made in the way macro expansion is performed.
Direct macro recursion is now permitted.
In the body of a macro, the name of that macro is not expanded.
For example
@(E
	#define func(arg) func((arg) + 1)
	func(count)
@)E
expands to
@(E
	func((count) + 1)
@)E
On the other hand the mutual recursion or macros is still not allowed.
The following definitions will cause an error if either macro is ever used:
@(E
	#define foo(x) fum(x)
	#define fum(y) foo(y)
@)E
Two new preprocessing operators,
.KW #
and
.KW ##
have been created.
The occurrence of
.KW #
followed by the name of a macro formal parameter is replaced by the
actual parameters surrounded by double-quotes.
This means that
@(E
	#define ld(file) load(#file)
	ld(foo.c)
@)E
expands to
@(E
	load("foo.c")
@)E
.PP
The occurrence of
.KW ##
in the body of a macro surrounded by any two tokens
expands to the concatenation of those two tokens.
For example
@(E
	#define debug(num) printf("%d\en", x ## num)
	debug(1)
@)E
expands to
@(E
	printf("%d\en", x1)
@)E
White space surrounding the
.KW ##
is ignored.
