ISO C
These following standards are equivalent (Harbison & Steele 1995):
- ANS X3.159-1989 - "ANSI C".
- ISO/IEC 9899:1990 - "ISO C".
Contents:
char, int, I/O and EOF
The following is very dangerous:
char ch; /* don't do this and ... */ ... while( (ch=fgetc(...)) != EOF ) /* ... also this. */ { ... }
because int fgetc(FILE *stream)
returns an int
, which will be truncated to the
char ch
and may or may not be sign-extended for comparison with the EOF
.
Such code behaves differently on
`silas', an `alpha', (OK) and on an `indy' (not OK), both using `gcc',
L.A. 10/1999!
Better is to make ch
an int
, and/or
separate the assignment to ch
from the test on EOF
,
particularly by using
int feof(FILE *stream)
to test for end-of-file.
NB.
"1.
Type char may be a signed integral type,
equivalent to signed char.
2.
Type char may be a signed integral type,
equivalent to unsigned char.
3.
Type char may be a pseudo-unsigned integral type -
that is, it can contain only non-negative values, but it is treated
as if it were a signed type when performing the usual unary conversions."
(Harbison & Steele 1995, p115).
NB. "The value EOF is conventionally used as a value that signals end-of-file - that is the exhaustion of input data. It has the value -1 in most traditional implementations, but ISO C requires only that it be a negative integral constant expression." (Harbison & Steel 1995, p345),
Go to the [top of the page].
Compilation
Large programs are usually split into more than one file for easy management. This also allows parts of the program to be (re)compiled separately and therefore more quickly.
The command make
is used to compile only
those parts of a program that have changed since the last compilations.
An attendant makefile
indicates dependencies between
the files that make up the complete program.
Try the command man make
to find out more about
make
.
For a modest program made up of a few
.c
and .h
files in one directory,
the following shortcut is quick and is usually sufficient:
gcc *.c
where gcc
is the gnu C compiler.
Go to the [top of the page].
Function Formal Parameters
int f() { .... } /* f is some function */ void rtn1( int g(void) ) /* g is a (function) formal parameter */ { int i; ....; i=g(); .... /* call actual parameter bound to g */ }/*rtn1*/ void rtn2(int (*h)(void)) /* param h, "classic" C style */ { int i; ....; i=h(); .... /* call actual parameter bound to h */ }/*rtn2*/ ... rtn1(f); /* call rtn1 with f bound to g */ /* NB. f is not called at this point */ rtn2(f); /* call rtn2 with f bound to h */
The first form, as in the definition of rtn1
is generally preferred because the syntax is much simpler.
The 2nd (classic C) form, as in the definition of rtn2
,
does illustrate how a function formal parameter
is implemented in either case,
i.e. as a pointer to the code for the function.
Both forms are valid.
e.g. See Harbison and Steele (1995) p270.
Go to the [top of the page].
References
- S. P. Harbison & G. L. Steele jr. C: A Reference Manual. Prentice Hall, 1995
Go to the [top of the page].
Lloyd Allison 1999