Category : C Source Code
Archive   : LOVE-C.ZIP
Filename : LOVE-TEX.TAR
Output of file : LOVE-TEX.TAR contained in archive : LOVE-C.ZIP
\typeout{**************************************************}
\typeout{***** New standard documentstyle option 'a4' *****}
\typeout{********* For old version, use 'a4_local' ********}
\typeout{**************************************************}
%NAME: a4.sty
% "a4" document style option.
% John Pavel, May 1987
%
% Redefines the \textheight and \topmargin for A4 paper, as opposed to US paper.
% \textwidth is not altered because A4 is narrower than US paper.
%
% \textheight is the height of text (including footnotes and figures,
% excluding running head and foot).
%
% Adjusting \textheight will adjust position of the bottom of the page.
% Must preserve "(\textheight - \topskip) divides \baselineskip".
% \topskip always appears to be 10pt.
%
%
% Following Lamport's change to other style files on 24 Jun 86,
% changed to explicitly compute \textheight to avoid roundoff. The
% value of the multiplier was calculated as the floor of the old
% \textheight minus \topskip, divided by \baselineskip for
% \normalsize.
%
%
%
\topmargin -0.5 in % Nominal distance from top of paper to top of page
\ifcase \@ptsize
% mods for 10 pt
\textheight 53\baselineskip
\or % mods for 11 pt
\textheight 46\baselineskip
\or % mods for 12 pt
\textheight 46\baselineskip
\fi
\advance\textheight by \topskip
love-tex/appendices.tex 100644 0 0 43777 5600705233 13577 0 ustar root root % Copyright (c) 1993 by T.P.Love. This document may be copied freely
% for the purposes of education and non-commercial research.
% Cambridge University Engineering Department,
% Cambridge CB2 1PZ, England.
\section{Examples}
\input{examples}
\section{More on Multidimensional Arrays and Pointers}
The elements of {\tt aai[4][2]} are stored in memory in the following order.
\noindent {\tt aai[0][0]aai[0][1]aai[1][0]aai[1][1]\\
aai[2][0]aai[2][1]aai[3][0]aai[3][1]}
{\tt *aai} is of type {\tt int[]}. Note that:-
\begin{verbatim}
aai[1][2] == *( (aai[1])+2) == *(*(aai+1)+2)
\end{verbatim}
and that numerically
\begin{verbatim}
aai == aai[0] == &aai[0][0]
\end{verbatim}
{\tt *aai} can be used as a pointer to the first element even though
it is of type {\tt `array 4 of int'} because it becomes
{\tt `pointer to int'} when used where a value is needed.
But {\tt *aai} is not equivalent to a pointer. For example, you can't change
its value. This distinction can easily and dangerously be blurred in
multi-file situations illustrated in the following example. In
\begin{verbatim}
extern int *foo;
\end{verbatim}
{\tt foo} is a variable of type {\tt pointer to int}.
{\tt foo}'s type is complete, {\tt (sizeof foo)} is allowed. You can assign
to foo. But given
\begin{verbatim}
extern int baz[];
\end{verbatim}
{\tt baz} is a variable of type `{\tt array UNKNOWN-SIZE of int}'.
This is an `incomplete' type, you can't take {\tt (sizeof baz)}.
You cannot assign to {\tt baz}, and although {\tt baz} will decay into a
pointer in most contexts, it is not possible for {\tt (baz == NULL)}
ever to be true.
The compiler will allow you to mix the array/pointer notation and will get
it right, but it needs to know what the reality is. Once you declare the
array/pointer correctly, you can then access it either way.
Suppose we have a simple array, and a subfunction for adding items to it:
\begin{verbatim}
#define MAXELTS 100
int array[MAXELTS];
int num_of_elements = 0;
install(x)
int x;
{
if(num_of_elements >= MAXELTS){
fprintf(stderr, "too many elements (max %d)\n", MAXELTS);
exit(1);
}
array[num_of_elements++] = x;
}
\end{verbatim}
Let's see how easy it is to remove the arbitrary limitation in
this code, by dynamically allocating the array:
\begin{verbatim}
#include
int *array = NULL;
int nalloc = 0;
int num_of_elements = 0;
install(x)
int x;
{
if(num_of_elements >= nalloc){
/* We've run out of space. Reallocate with space for 10 more ints */
nalloc += 10;
array = (int *)realloc((char *)array, nalloc * sizeof(int));
if(array == NULL){
fprintf(stderr, "out of memory with %d elements\n", num_of_elements);
exit(1);
}
}
array[num_of_elements++] = x;
}
\end{verbatim}
Be sure that realloc is declared correctly. If you don't have
{\tt
want to be
true-blue ANSI, use {\tt size\_t} for {\tt nalloc} and {\tt num\_of\_elements}.
When dynamically allocating a multidimensional array,
it is usually best to allocate an array of pointers, and then
initialize each pointer to a dynamically-allocated ``row''. The
resulting ``ragged" array can save space, although it is not
necessarily contiguous in memory as a real array would be. Here is
a two-dimensional example:
\begin{verbatim}
/* create an array of pointers */
int **array = (int **)malloc(nrows * sizeof(int *));
if (array == NULL){
fprintf(stderr,"Out of memory\n");
exit(1);
}
for(i = 0; i < nrows; i++){
/* create space for an array of ints */
array[i] = (int *)malloc(ncolumns * sizeof(int));
if (array[i] == NULL){
fprintf(stderr,"Out of memory\n");
exit(1);
}
}
\end{verbatim}
You can keep the array's contents contiguous, while making later
reallocation of individual rows difficult, with a bit of explicit
pointer arithmetic:
\begin{verbatim}
int **array = (int **)malloc(nrows * sizeof(int *));
if (array == NULL){
fprintf(stderr,"Out of memory\n");
exit(1);
}
array[0] = (int *)malloc(nrows * ncolumns * sizeof(int));
if (array[0] == NULL){
fprintf(stderr,"Out of memory\n");
exit(1);
}
for(i = 1; i < nrows; i++)
array[i] = array[0] + i * ncolumns;
\end{verbatim}
In either case, the elements of the dynamic array can be accessed
with normal-looking array subscripts: {\tt array[i][j]}.
If the double indirection implied by the above schemes is for some
reason unacceptable, you can simulate a two-dimensional array with
a single, dynamically-allocated one-dimensional array:
\begin{verbatim}
int *array = (int *)malloc(nrows * ncolumns * sizeof(int));
\end{verbatim}
However, you must now perform subscript calculations manually,
accessing the {\tt i},{\tt j} th element with
{\tt array[i * ncolumns + j]}.
\section{Signals and error handling}
Various signals (interrupts) can be received by your program. See
the {\tt signal.h} include file for a list. You can trap them if you
wish, or simply ignore them. \Eg
\begin{verbatim}
#include
...
/* this will ignore control-C */
signal(SIGINT, SIG_IGN);
\end{verbatim}
The following code sets a `timebomb'. After {\tt Timer} is called,
the program will continue execution until `{\tt n}' milliseconds
have passed, then normal execution will be interrupted and
`{\tt onalarm()}' will be called before normal execution is resumed.
\begin{verbatim}
#include
/*******/
static void onalarm()
/*******/
{
something();
signal(SIGALRM,SIG_DFL);
}
...
/*******/
void Timer(n) /* waits for 'n' milliseconds */
int n;
/*******/
{
long usec;
struct itimerval it;
if (!n) return;
usec = (long) n * 1000;
memset(&it, 0, sizeof(it));
if (usec>=1000000L) { /* more than 1 second */
it.it_value.tv_sec = usec / 1000000L;
usec %= 1000000L;
}
it.it_value.tv_usec = usec;
signal(SIGALRM,onalarm);
setitimer(ITIMER_REAL, &it, (struct itimerval *)0);
}
\end{verbatim}
This same method can be used to catch emergency signals like
{\tt SIGBUS} (bus error) too.
\section{\ANSI }
In 1983, the American National Standards Institute commissioned a
committee, X3J11, to standardize the C language. After a long,
arduous process, including several widespread public reviews, the
committee's work was finally ratified as an American National
Standard, X3.159-1989, on December 14, 1989, and published in the
spring of 1990. For the most part, \ANSI\ standardizes existing
practice, with a few additions from {\tt C++} (most notably function
prototypes) and support for multinational character sets (including
the much-lambasted trigraph sequences). The \ANSI\ standard also
formalizes the C run-time library support functions.
The published Standard includes a ``Rationale," which explains many
of its decisions, and discusses a number of subtle points,
including several of those covered here. (The Rationale is ``not
part of ANSI Standard X3.159-1989, but is included for information
only.")
The Standard has been adopted as an international standard, ISO/IEC
9899:1990, although the Rationale is currently not included.
\subsection{Converting to \ANSI }
\label{KRTOANSI}
Many \KandR\ programs compile with an \ANSI\ compiler without changes.
Where changes are required, the compiler will nearly always tell you.
A list of differences between \KandR\ and \ANSI\ is in \cite{KandR}.
The most important are
\begin{description}
\item[Function prototyping :- ]
Function prototypes aren't mandatory in \ANSI , but they improve
error checking. Their use enables certain \ANSI\ features which otherwise,
for backward compatibility, are suppressed.
\item[Parameter Passing :- ]
\begin{itemize}
\item Floats are passed as floats (in \KandR\ floats are converted to
doubles when passed to a function)
\item Arguments are automatically cast into the right form for the
called function. Without the function prototyping the following
program wouldn't work because `{\tt mean}' is expecting 2 integers.
\begin{verbatim}
#include
#include
int mean(int a,int b)
{
return a + b;
}
main()
{
int i;
float f;
int answer;
i = 7;
f= 5.3;
/* deliberate mistake! */
answer = mean(f,j);
printf("%f + %d = %d\n", f, j, answer);
}
\end{verbatim}
\end{itemize}
\item[Standardisation :- ]
The standard include files for \ANSI\ are
\begin{center}
\begin{tabular}{ll}
{\tt assert.h} & Assertions \\
{\tt ctype.h} & Character identification \\
{\tt errno.h} & Error handling\\
{\tt float.h} & Max and Min values for floats\\
{\tt limits.h} & limits for integral types\\
{\tt locale.h} & Internationalisation info\\
{\tt math.h} & Advanced math functions\\
{\tt setjmp.h} & Non-local jump\\
{\tt signal.h} & Exception handling\\
{\tt stdarg.h} & Variable numbers of arguments\\
{\tt stddef.h} & Standard definitions\\
{\tt stdio.h} & Input/Output\\
{\tt stdlib.h} & General Utilities\\
{\tt string.h} & String Manipulation\\
{\tt time.h} & Date and Time functions
\end{tabular}
\end{center}
\end{description}
If you want to support both \ANSI\ and \KandR\ , you can use the
following construction
\begin{verbatim}
#ifdef __STDC__
/* ANSI code */
#else
/* K and R code */
#endif
\end{verbatim}
\section{Numerical Analysis}
One problem when writing numerical algorithms is obtaining machine
constants.
On Sun's they can be obtained in {\tt
The \ANSI\ standard recommends that such constants be defined in the
header file {\tt
Sun's and standards apart, these values are not always readily available,
The NCEG (Numerical C Extensions Group) is working on proposing standard
extensions to C for numerical work, but nothing's ready yet, so
before you do any heavy computation, especially with real numbers, I
suggest that you browse through a {\tt Numerical Analysis} book.
Common problems that you might face are :-
\begin{description}
\item[Testing for equality :- ]
Real numbers are handled in ways that don't guarantee expressions to yield
exact results. It's risky to test for equality. Better is to
use something like
\begin{verbatim}
d = max(1.0, fabs(a), fabs(b))
\end{verbatim}
and then test
\verb|fabs(a - b) / d| against a relative error margin. Useful constants
in \verb|float.h| are \verb|FLT_EPSILON|, \verb|DBL_EPSILON|,
and \verb|LDBL_EPSILON|, defined to be the smallest numbers such that
\begin{verbatim}
1.0f + FLT_EPSILON != 1.0f
1.0 + DBL_EPSILON != 1.0
1.0L + LDBL_EPSILON != 1.0L
\end{verbatim}
respectively.
\item[Avoiding over- and underflow :- ]
You can test the operands before performing an operation in order to
check whether the operation would work. You should always avoid dividing
by zero. For other checks,
split up the numbers into fractional and exponent part using
the \verb|frexp()| and \verb|ldexp()| library functions and compare the
resulting values against \verb|HUGE| (all in \verb|
\item[Floats and Doubles :- ]
\KandR\ encouraged the interchangeable use of
{\tt float} and {\tt double} since all expressions with
such data types where always evaluated using the {\tt double} representation
-- a real nightmare for those implementing efficient numerical algorithms
in C. This rule applied, in particular, to floating-point arguments and
for most compilers around it does not matter whether one defines the argument
as {\tt float} or {\tt double}.
According to the \ANSI\ standard such programs will continue to exhibit the same
behavior {\em as long as one does not prototype the function}. Therefore, when
prototyping functions make sure the prototype is included when the function
definition is compiled so the compiler can check if the arguments match.
\begin{itemize}
\item Keep in mind that the {\tt double} representation does not
necessarily increase the {\em precision}. Actually, in most implementations
the worst-case precision decreases but the {\em range} increases.
\item Do not use {\tt double} unnecessarily since in most cases there is
a large performance penalty. Furthermore, there is no point in using higher
precision if the additional bits which will be computed are garbage anyway.
The precision one needs depends mostly on the precision of the input data
and the numerical method used.
\end{itemize}
\item[Infinity :- ]
The IEEE standard for floating-point recommends a set of functions to
be made available. Among these are functions to classify a value
as {\tt NaN}, {\tt Infinity}, {\tt Zero}, {\tt Denormalized},
{\tt Normalized}, and so on. Most
implementations provide this functionality,
although there are no standard names for the functions. Such
implementations often provide predefined identifiers (such as
\verb|_NaN|, \verb|_Infinity|, etc) to allow you to generate these values.
If {\tt x} is a floating point variable, then {\tt (x != x)} will be
TRUE if and only if {\tt x} has the value {\tt NaN}.
Many C implementations claim to be IEEE 748 conformant, but if you try
the {\tt (x!=x)} test above with {\tt x} being a {\tt NaN}, you'll find
that they aren't.
In the mean time, you can write your own `standard' functions and macros,
and provide versions of them for each system you use. If the system
provides the functions you need, you \verb|#define| your `standard' functions
to be the system functions. Otherwise, you write your function as an
interface to what the system provides, or write your own from scratch.
\end{description}
See {\tt matherr(3)} for details on how to cope with errors once they've
happened.
See the \verb|CUED help/languages/C/math_routines| file in the
{\tt gopher.eng.cam.ac.uk}
gopher for a long list of available resources.
\section{Fortran and C}
Here are some opinions that experienced programmers have given for why
{\bf fortran} has not been replaced by C:
\begin{itemize}
\item ``C is definitely for wizards, not beginners or casual programmers.
Usually people who are heavily into numerical work are not hacker
types. They are mathematicians, scientists, or engineers. They
want to do calculations, not tricky pointer manipulations.
{\bf fortran}'s constructs are more obvious to use, while even simple
programs in C tend to be filled with tricks. Even the fundamental
operation of reading input can be tricky in C.''
\item ``{\bf fortran} is dangerous to use, but not as dangerous as C. For
instance, most {\bf fortran} compilers have subscript checking as an
option, while I have never encountered a C compiler with this
feature. The ANSI standard for function prototypes will
give C an edge over {\bf fortran} in parameter mismatch error.''
\item ``There is a large body of well tested mathematical packages available
for {\bf fortran}, that are not yet available in C. For example the
IMSL package. However, this situation is improving for C.''
\item ``In studies done at Cray Research, they
found it took {\em significantly} longer for their programmers to learn C
and the number of errors generated in coding in C (as opposed to
{\bf fortran}) was much higher.''
\item ``C is hard to optimize, especially if the programmer makes full use
of C's expressivity. Newer C features (like the {\tt const} keyword etc)
and new software technology are improving the situation.''
\item ``C has too many system dependent aspects (e.g. round up or down when
dividing negative integers).''
\end{itemize}
Whether or not the switch to C is worthwhile will depend on whether
its quirks outweigh the benefits of having ``more modern"
data typing and control structures. \ANSI\ goes a long way to removing
the quirks but for the time being {\bf fortran} is probably more portable
and will run faster on supercomputers without tweaking. On the other hand
{\bf fortran} may be
harder to maintain, and it is a poor fit to algorithms that are best
expressed with types more involved than n-dimensional arrays.
When {\tt Fortran9X} becomes commonplace, perhaps the decision will be
easier to make.
\section{Calling Fortran from C}
See the {\em Portability Guide} manual if you intend doing this on
HP machines. Rudi Vankemmel ({\tt [email protected]}) mentions some general
points that are worth noting :-
\begin{enumerate}
\item Fortran uses a column wise storage of matrices while C stores them
row wise. This means that when you want to parse a matrix from your
C-program to the fortran routine you must transpose the matrix
in your program before entering the routine. Of course, any output
from such a routine must be transposed again.
If you omit this step, then probably your program will run (because
it has data to compute on) but it will generate wrong answers.
If you have the Fortran source code (of any routine) then
on some platforms you may use compiler directives specifying
that the Fortran compiler must use row wise storage. Some platforms
support these directives. However watch out with this if you call
the same routine from another Fortran routine/program.
\item Your Fortran compiler may add an underscore to the routine name
in the symbol table. Hence in the calling C-program/routine
you must add a trailing underscore ! Otherwise the loader will complain
about an undefined symbol.
However, check your compiler for this. For example the Fortran compiler
on VAX-VMS systems does NOT add a trailing underscore (there watch out
with the fact that the VAX-Fortran compiler translates everything
in uppercase).
\item Fortran passes its variables by reference. This means that you MUST
give adresses in your calling C-program.
\item Watch out especially with {\tt float}s and {\tt double}s. Make sure
that the
size of the variable in the calling program is identical to the size
in the Fortran routine.
This is extremely important on machines with little endian byte
ordering. Parsing a {\tt float} (C-routine) to a {\tt real*8}
(Fortran) number will not generate SEGV but give wrong results as the
data is parsed wrongly.
\end{enumerate}
love-tex/bitmap.sty 100644 0 0 3511 5600705266 12723 0 ustar root root %
% Taken from TUGboat, Volume 12 (1991), No2. pp 229-232
% Arguments: {bitmap file}{pixel size}
% Example
% \documentstyle[a4_local,bitmap]{article}
% \begin{document}
% \Bitmap{/usr/local/include/X11/bitmaps/cued_icons/kettle.px}{1pt}
% Now in a frame
% \fbox{\vbox{\Bitmap{/usr/local/include/X11/bitmaps/cued_icons/xpc.px}{1pt}}}
% \end{document}
%
%
%
\newcount\bmhpoz
\newcount\bmwid
\newif \ifbmblack
\newdimen\bmrlen
\newdimen\bmpsiz
\catcode`,=\active
\def\Bitmap#1#2{\bgroup
\bmpsiz=#2
\baselineskip=\bmpsiz
\parindent=0pt
\bmrlen=0pt
% define `,' so that the succeeding number is
% processed
\catcode`,=\active
\def,##10x##2##3{%
\HexFig{##3}\HexFig{##2}%
\advance\bmhpoz 8
\ifnum\bmhpoz>\bmwid
% check the current y position against the
% bitmap width
\0\hfil \vskip 0pt
\bmhpoz=1 \bmrlen=0pt
\fi}
\def\HexFig##1{%
%convert a hex figure into 4 calls of \0 or \1
\uppercase{\ifcase "##1}
\0\0\0\0\or
\1\0\0\0\or
\0\1\0\0\or
\1\1\0\0\or
\0\0\1\0\or
\1\0\1\0\or
\0\1\1\0\or
\1\1\1\0\or
\0\0\0\1\or
\1\0\0\1\or
\0\1\0\1\or
\1\1\0\1\or
\0\0\1\1\or
\1\0\1\1\or
\0\1\1\1\or
\1\1\1\1\fi
}
% convert the dots into \vrules (Invisible ones for white)
% \bmrlen stores the number of consecutive dots of the current
% color stored in \ifbmblack.
\def\0{\ifbmblack
\vrule width \bmrlen height \bmpsiz
\bmrlen=\bmpsiz \bmblackfalse
\else
\advance \bmrlen\bmpsiz
\fi}
\def\1{\ifbmblack
\advance \bmrlen\bmpsiz
\else
\vrule width \bmrlen height 0pt
\bmrlen=\bmpsiz \bmblacktrue
\fi}
% Parse the bitmap file.
% The width is read in as #2, the hex values as #5. Everything else
% is discarded.
\def\BmContent
##1_width ##2 ##3[] ##4 ##5;{%
\bmwid=##2 \hsize \bmwid\bmpsiz
\bmhpoz=1
,##5
}% end of \BmContent
\expandafter\BmContent\@@input #1
\egroup}% end of \Bitmap
\catcode`,=12 % other love-tex/comp.latex 100644 0 0 3235 5600705267 12707 0 ustar root root \setlength{\unitlength}{0.0125in}%
\begin{picture}(475,135)(20,645)
\put(342,716){\makebox(0,0)[b]{\raisebox{0pt}[0pt][0pt]{\sevrm Object}}}
\put(342,706){\makebox(0,0)[b]{\raisebox{0pt}[0pt][0pt]{\sevrm File}}}
\thicklines
\put(442,700){\framebox(53,27){}}
\put(471,709){\makebox(0,0)[b]{\raisebox{0pt}[0pt][0pt]{\sevrm Executable}}}
\put(300,715){\vector( 1, 0){ 20}}
\put( 60,715){\vector( 1, 0){ 20}}
\put(155,715){\vector( 1, 0){ 10}}
\put(220,715){\vector( 1, 0){ 20}}
\put(360,715){\vector( 1, 0){ 25}}
\put(425,715){\vector( 1, 0){ 15}}
\put(340,675){\vector( 2, 1){ 60}}
\put(116,759){\vector( 0,-1){ 40}}
\put( 76,760){\framebox(79,20){}}
\put(400,755){\vector( 0,-1){ 30}}
\put(324,700){\framebox(37,27){}}
\put( 80,645){\framebox(75,25){}}
\put(346,659){\makebox(0,0)[b]{\raisebox{0pt}[0pt][0pt]{\sevrm user's object files}}}
\put(115,675){\vector( 0, 1){ 35}}
\put(365,760){\framebox(80,20){}}
\put(305,645){\framebox(75,25){}}
\put( 20,700){\framebox(40,30){}}
\put( 41,719){\makebox(0,0)[b]{\raisebox{0pt}[0pt][0pt]{\sevrm Source}}}
\put( 41,707){\makebox(0,0)[b]{\raisebox{0pt}[0pt][0pt]{\sevrm File}}}
\put(192,711){\makebox(0,0)[b]{\raisebox{0pt}[0pt][0pt]{\tenbf Compiler}}}
\put(268,711){\makebox(0,0)[b]{\raisebox{0pt}[0pt][0pt]{\tenbf Assembler}}}
\put(406,711){\makebox(0,0)[b]{\raisebox{0pt}[0pt][0pt]{\tenbf Loader}}}
\put(116,711){\makebox(0,0)[b]{\raisebox{0pt}[0pt][0pt]{\tenbf Preprocessor}}}
\put(116,768){\makebox(0,0)[b]{\raisebox{0pt}[0pt][0pt]{\sevrm system include files}}}
\put(116,659){\makebox(0,0)[b]{\raisebox{0pt}[0pt][0pt]{\sevrm user's include files}}}
\put(404,768){\makebox(0,0)[b]{\raisebox{0pt}[0pt][0pt]{\sevrm system libraries}}}
\end{picture}
love-tex/examples.tex 100644 0 0 20477 5600705267 13301 0 ustar root root % Copyright (c) 1993 by T.P.Love. This document may be copied freely
% for the purposes of education and non-commercial research.
% Cambridge University Engineering Department,
% Cambridge CB2 1PZ, England.
\subsection{Command Line arguments}
\label{ARGC}
{\small
\begin{verbatim}
#include
#include
/* This shows how args can be read from the Unix command line */
int main(int argc, char *argv[]){
int i;
printf("The arguments are\n", argc);
for (i=1; i
exit (0);
}
\end{verbatim}
}
\subsection{Using {\tt qsort}, random numbers and the clock}
{\small
\begin{verbatim}
#include
#include
#include
* compile on HPs using c89 -D_HPUX_SOURCE -o filename filename.c */
#define NUM 10
int comp(const void *a, const void *b )
{
return *(int *)a - * (int *)b;
}
int main(int argc, char *argv[])
{
int numbers[NUM];
int i;
srand48((long)time(NULL));
printf("\nUnsorted numbers are:-\n");
for (i=0; i< NUM; i++){
numbers[i]= 1000 * drand48();
printf("%d: %3d\n", i, numbers[i]);
}
/* See the qsort man page for an explanation of the following */
qsort((void*) numbers, (size_t) NUM, sizeof(int), comp);
printf("\nSorted numbers are:-\n");
for (i=0; i< NUM; i++)
printf("%d:%3d\n", i, numbers[i]);
exit(0);
}
\end{verbatim}
}
\subsection{Calling other programs}
The commands used from the command line can be called from C.
{\small
\begin{verbatim}
#include
#include
int main(int argc, char *argv[]){
FILE *popen();
FILE *fp;
char string[32];
/* First use the system() call. Output will go to stdout. */
system("date");
/* Now `capture' the output of date using popen() */
fp = popen("date","r");
if (fp == NULL)
fprintf(stderr,"Cannot run date\n");
else{
fgets(string, 32, fp);
printf("The date command returns [%s]\n", string);
pclose(fp);
}
}
\end{verbatim}
}
\subsection{Linked Lists}
\label{LINKEDLIST}
The following program creates a singly linked list. Pointers are
maintained to the head and tail of the list.
\begin{figure}[hbt]
\begin{center}
\input{lists.latex}
\end{center}
\caption{Linked List}
\end{figure}
{\small
\begin{verbatim}
#include
typedef struct _list_item {
int val;
struct _list_item *next;
} list_item;
/* prototypes */
list_item *add_list_item(list_item *entry, int value);
void print_list_items(void);
list_item *head=NULL;
list_item *tail=NULL;
main(int argc, char *argv[])
{
tail=add_list_item(tail,5);
tail=add_list_item(tail,7);
tail=add_list_item(tail,2);
print_list_items();
}
list_item *add_list_item(list_item *entry, int value)
{
list_item *new_list_item;
new_list_item=(list_item*)malloc(sizeof(list_item));
if (entry==NULL){
head=new_list_item;
printf("First list_item in list\n");
}
else {
entry->next = new_list_item;
printf("Adding %d to list. Last value was %d \n",value,entry->val);
}
new_list_item->val = value;
new_list_item->next = NULL;
return new_list_item;
}
void print_list_items(void)
{
list_item *ptr_to_list_item;
for (ptr_to_list_item= head;ptr_to_list_item!= NULL;
ptr_to_list_item=ptr_to_list_item->next) {
printf("Value is %d \n", ptr_to_list_item->val);
}
}
\end{verbatim}
}
\subsection{Using pointers instead of arrays}
{\small
\begin{verbatim}
#include "stdio.h"
char *words[]={"apple","belt","corpus","daffodil","epicycle","floppy",
"glands","handles","interfere","jumble","kick","lustiness",
"glands","handles","interfere","jumble","kick","lustiness",
"glands","handles","interfere","jumble","kick","lustiness",
"glands","handles","interfere","jumble","kick","lustiness",
"glands","handles","interfere","jumble","kick","lustiness",
"glands","handles","interfere","jumble","kick","lustiness",
"glands","handles","interfere","jumble","kick","lustiness",
"glands","handles","interfere","jumble","kick","lustiness",
"glands","handles","interfere","jumble","kick","lustiness",
"mangleworsel","nefarious","oleangeous","parsimonious",NULL};
void slow(void)
{
int i,j,count=0;
for (i=0; words[i] != NULL ; i=i+1)
for (j=0; j <= strlen(words[i]) ; j=j+1)
if(words[i][j] == words[i][j+1])
count= count+1;
printf("count %d\n",count);
}
void fast(void)
{
register char **cpp; /* cpp is an array of pointers to chars */
register char *cp;
register int count=0;
for (cpp= words; *cpp ; cpp++) /* loop through words. The final
NULL pointer terminates the loop */
for (cp = *cpp ; *cp ; cp++) /* loop through letters of a word.
The final '\0' terminates the loop */
if(*cp == *(cp+1))
count++;
printf("count %d\n",count);
}
/*count the number of double letters, first using arrays, then pointers */
void main(int argc, char *argv[]){
slow();
fast();
}
\end{verbatim}
}
\subsection{A data filter}
The program reads from {\tt stdin} an {\tt ASCII} file containing values
of a variable {\em y} for integral values of {\em x} running from 0
to {\em n-1} where {\em n} is the number of values in the file.
There may be several values on each line. The program outputs
the {\em x, y} pairs, one pair per line, the {\em y} values
scaled and translated.
{\small
\begin{verbatim}
#include
#include
int answer;
float offset;
float scale;
char buf[BUFSIZ];
int xcoord = 0;
char *cptr;
int transform(int a)
{
return a * scale + offset + 0.5;
}
char* eat_space(char *cptr){
/* This while loop skips to the nonspace after spaces.
If this is the end of the line, return NULL
`While a space, keep going'
*/
while (*cptr ==' '){
if (*cptr == '\0')
return NULL;
else
cptr++;
}
return cptr;
}
char * next_next_num(char *cptr){
/* This while loop skips to the 1st space after a number.
If this is the end of the line, return NULL
`While NOT a space, keep going'
*/
while (*cptr !=' '){
if (*cptr == '\0')
return NULL;
else
cptr++;
}
/* Now move to the start of the next number */
return eat_space(cptr);
}
int main(int argc, char *argv[])
{
offset = 2.3;
scale = 7.5;
while(1){
/* if we haven't reached the end of the file ...*/
if(fgets(buf, BUFSIZ,stdin)!= NULL){
/* initialise cptr to point to the first number ...*/
cptr = eat_space(buf);
do{
/* convert the representation of the num into an int */
sscanf(cptr,"%d", &num);
/* print x and y to stdout */
printf("%d %d\n",xcoord, tranform(num));
/* skip to the start of the next number on the line */
cptr=next_next_num(cptr);
xcoord++;
}while ( cptr!=NULL);
}
else{
exit(0);
}
}
}
\end{verbatim}
}
\subsection{Reading Directories}
{\small
\begin{verbatim}
#include
#include
#include
#include
#define REQUEST_DIR "/"
int main(int argc, char *argv[]){
FILE *fp;
DIR *dirp;
struct dirent *dp;
struct stat buf;
dirp = opendir(REQUEST_DIR);
chdir(REQUEST_DIR);
/* Look at each entry in turn */
while ((dp = readdir(dirp)) != NULL) {
/* Now stat the file to get more information */
if (stat(dp->d_name, &buf) == -1)
perror("stat\n");
if (S_ISDIR(buf.st_mode))
printf("%s is a directory\n", dp->d_name);
else if (S_ISREG(buf.st_mode))
printf("%s is a regular file\n", dp->d_name);
}
(void) closedir(dirp);
}
\end{verbatim}
}
\subsection{Queens: recursion and bit arithmetic}
This program counts the number of ways that 8 queens can be placed
on a chess board without any 2 of them being on the same row, column or
diagonal.
It was written by M. Richards at {\tt cam.cl}
{\small
\begin{verbatim}
#include
int count;
void try(int row, int ld, int rd){
if (row == 0xFF)
count++;
else{
int poss = 0xFF & ~(row | ld | rd);
while (poss){
int p = poss& -poss;
poss = poss -p;
try(row+p, (ld+p)<<1, (rd+p)>>1);
}
}
}
int main(int argc, char *argv[]){
printf("Eight Queens\n");
count = 0;
try(0,0,0);
printf("Number of solutions is %d\n", count);
exit(0);
}
\end{verbatim}
}
love-tex/fancyheadings.sty 100644 0 0 22742 5600705270 14274 0 ustar root root %NAME: fancyheadings.sty
% fancyheadings.sty version 1.0
% Fancy headers and footers.
% Piet van Oostrum, Dept of Computer Science, University of Utrecht
% Padualaan 14, P.O. Box 80.089, 3508 TB Utrecht, The Netherlands
% Telephone: +31-30-531806. [email protected] (mcvax!hp4nl!ruuinf!piet)
% March, 1989.
% Here is a documentstylestyle option that allows you to customize your
% page headers and footers in an easy way. It combines features that were
% separately available in other pagestyles, without introducing much
% complexity. You can define:
% - three-part headers and footers
% - rules in header and footer
% - headers and footers wider than \textwidth
% - multiline headers and footers
% - separate headers and footers for even and odd pages
% - separate headers and footers for chapter pages
%
% To use this pagestyle, you must include the ``fancyheadings'' style
% option in your \documentstyle, and issue the \pagestyle{fancy} command.
% The \pagestyle{fancy} command should be issued after any changes made to
% \textwidth.
%
% The page layout will be as follows:
%
% LHEAD CHEAD RHEAD
% ----------------------------------- (rule)
%
% page body
%
%
% ----------------------------------- (rule)
% LFOOT CFOOT RFOOT
%
% The L-fields will be leftadjusted, the C-fields centered and the
% R-fields rightadjusted.
% Each of the six fields and the two rules can be defined separately.
%
% Simple use:
%
% The header and footer fields can be defined by commands \lhead{LHEAD}
% and so on for the other fields. If the field depends on something in the
% document (e.g. section titles) you must in general use the \markboth and
% \markright commands, otherwise a title may end on the wrong page. You
% can do this e.g. by redefining the commands \chaptermark, \sectionmark
% and so on (see example below). The defaults for these marks are as in
% the standard pagestyles. The marks can be put into a header or footer
% field by referencing \leftmark and \rightmark.
%
% Rules in header and footer
%
% The thickness of the rules below the header and above the footer can be
% changed by redefining the length parameters \headrulewidth (default
% 0.4pt) and \footrulewidth (default 0). These may be redefined by the
% \setlength command. A thickness of 0pt makes the rule invisible.
% If you want to make more complicated changes, you have to redefine the
% commands \headrule and/or \footrule.
%
% Headers and footers wider than \textwidth
%
% The headers and footers are set in a box of width \headwidth. The
% default for this is the value of \textwidth. You can make it wider (or
% smaller) by redefining \headwidth with the \setlength or \addtolength
% command. The headers and footers will stick out the page on the same
% side as the marginal notes. For example to include the marginal notes,
% add both \marginparsep and \marginparwidth to \headwidth (see also the
% example below).
%
% Multiline headers and footers
%
% Each of the six fields is set in an appropriate parbox, so you can put a
% multiline part in it with the \\ command. It is also possible to put
% extra space in it with the \vspace command. Note that if you do this you
% will probably have to increase the \headheight or \footskip lengths.
%
% Separate headers and footers for even and odd pages
%
% If you want the headers and footers to be different on even- and
% odd-numbered pages in the ``twoside'' style, the field-defining macros
% can be given an optional argument, to be used on the even-numbered
% pages, like \lhead[EVEN-LHEAD]{ODD-RHEAD}.
%
% Separate headers and footers for chapter pages
%
% LaTeX gives a \thispagestyle{plain} command for the first page of the
% document, the first page of each chapter and a couple of other pages. It
% might be incompatible with your pagestyle. In this case you can use a
% slightly different version of the pagestyle, called \pagestyle{fancyplain}.
% This pagestyle redefines the pagestyle ``plain'' to also use pagestyle
% ``fancy'' with the following modifications:
% - the thicknesses of the rules is defined by \plainheadrulewidth and
% \plainfootrulewidth (both default 0).
% - the 6 fields may be defined separately for the plain pages by
% giving them the value \fancyplain{PLAIN-VALUE}{NORMAL-VALUE}. This
% construct may be used in both the optional argument and the normal
% argument. Thus \lhead[\fancyplain{F1}{F2}]{\fancyplain{F3}{F4}}
% specifies the LHEAD value in a two-sided document:
% F1 on an even-numbered ``plain'' page
% F2 on an even-numbered normal page
% F3 on an odd-numbered ``plain'' page
% F4 on an odd-numbered normal page.
%
% Defaults:
%
% \headrulewidth 0.4pt
% \footrulewidth 0pt
% \plainheadrulewidth 0pt
% \plainfootrulewidth 0pt
%
% \lhead[\fancyplain{}{\sl\rightmark}]{\fancyplain{}{\sl\leftmark}}
% % i.e. empty on ``plain'' pages \rightmark on even, \leftmark on odd pages
% \chead{}
% \rhead[\fancyplain{}{\sl\leftmark}]{\fancyplain{}{\sl\rightmark}}
% % i.e. empty on ``plain'' pages \leftmark on even, \rightmark on odd pages
% \lfoot{}
% \cfoot{\rm\thepage} % page number
% \rfoot{}
%
% Examples:
%
% To put two lines containing the section title and the subsection title
% in the righthandside corner, use:
%
% \documentstyle[fancyheadings]{article}
% \pagestyle{fancy}
% \renewcommand{\sectionmark}[1]{\markboth{#1}{}}
% \renewcommand{\subsectionmark}[1]{\markright{#1}}
% \rfoot{\leftmark\\\rightmark}
%
% The following definitions give an approximation of the style used in the
% LaTeX book:
%
% \documentstyle[fancyheadings]{book}
% \pagestyle{fancyplain}
% \addtolength{\headwidth}{\marginparsep}
% \addtolength{\headwidth}{\marginparwidth}
% \renewcommand{\chaptermark}[1]{\markboth{#1}{#1}} % remember chapter title
% \renewcommand{\sectionmark}[1]{\markright{\thesection\ #1}}
% % section number and title
% \lhead[\fancyplain{}{\bf\thepage}]{\fancyplain{}{\bf\rightmark}}
% \rhead[\fancyplain{}{\bf\leftmark}]{\fancyplain{}{\bf\thepage}}
% \cfoot{}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\def\lhead{\@ifnextchar[{\@xlhead}{\@ylhead}}
\def\@xlhead[#1]#2{\gdef\@elhead{#1}\gdef\@olhead{#2}}
\def\@ylhead#1{\gdef\@elhead{#1}\gdef\@olhead{#1}}
\def\chead{\@ifnextchar[{\@xchead}{\@ychead}}
\def\@xchead[#1]#2{\gdef\@echead{#1}\gdef\@ochead{#2}}
\def\@ychead#1{\gdef\@echead{#1}\gdef\@ochead{#1}}
\def\rhead{\@ifnextchar[{\@xrhead}{\@yrhead}}
\def\@xrhead[#1]#2{\gdef\@erhead{#1}\gdef\@orhead{#2}}
\def\@yrhead#1{\gdef\@erhead{#1}\gdef\@orhead{#1}}
\def\lfoot{\@ifnextchar[{\@xlfoot}{\@ylfoot}}
\def\@xlfoot[#1]#2{\gdef\@elfoot{#1}\gdef\@olfoot{#2}}
\def\@ylfoot#1{\gdef\@elfoot{#1}\gdef\@olfoot{#1}}
\def\cfoot{\@ifnextchar[{\@xcfoot}{\@ycfoot}}
\def\@xcfoot[#1]#2{\gdef\@ecfoot{#1}\gdef\@ocfoot{#2}}
\def\@ycfoot#1{\gdef\@ecfoot{#1}\gdef\@ocfoot{#1}}
\def\rfoot{\@ifnextchar[{\@xrfoot}{\@yrfoot}}
\def\@xrfoot[#1]#2{\gdef\@erfoot{#1}\gdef\@orfoot{#2}}
\def\@yrfoot#1{\gdef\@erfoot{#1}\gdef\@orfoot{#1}}
\newdimen\headrulewidth
\newdimen\footrulewidth
\newdimen\plainheadrulewidth
\newdimen\plainfootrulewidth
\newdimen\headwidth
\newif\if@fancyplain \@fancyplainfalse
\def\fancyplain#1#2{\if@fancyplain#1\else#2\fi}
% Initialization of the head and foot text.
\headrulewidth 0.4pt
\footrulewidth\z@
\plainheadrulewidth\z@
\plainfootrulewidth\z@
\lhead[\fancyplain{}{\sl\rightmark}]{\fancyplain{}{\sl\leftmark}}
% i.e. empty on ``plain'' pages \rightmark on even, \leftmark on odd pages
\chead{}
\rhead[\fancyplain{}{\sl\leftmark}]{\fancyplain{}{\sl\rightmark}}
% i.e. empty on ``plain'' pages \leftmark on even, \rightmark on odd pages
\lfoot{}
\cfoot{\rm\thepage} % page number
\rfoot{}
% Put together a header or footer given the left, center and
% right text, fillers at left and right and a rule.
% The \lap commands put the text into an hbox of zero size,
% so overlapping text does not generate an errormessage.
\def\@fancyhead#1#2#3#4#5{#1\hbox to\headwidth{\vbox{\hbox
{\rlap{\parbox[b]{\headwidth}{\raggedright#2\strut}}\hfill
\parbox[b]{\headwidth}{\centering#3\strut}\hfill
\llap{\parbox[b]{\headwidth}{\raggedleft#4\strut}}}\headrule}}#5}
\def\@fancyfoot#1#2#3#4#5{#1\hbox to\headwidth{\vbox{\footrule
\hbox{\rlap{\parbox[t]{\headwidth}{\raggedright#2\strut}}\hfill
\parbox[t]{\headwidth}{\centering#3\strut}\hfill
\llap{\parbox[t]{\headwidth}{\raggedleft#4\strut}}}}}#5}
\def\headrule{{\if@fancyplain\headrulewidth\plainheadrulewidth\fi
\hrule\@height\headrulewidth\@width\headwidth \vskip-\headrulewidth}}
\def\footrule{{\if@fancyplain\footrulewidth\plainfootrulewidth\fi
\vskip-0.3\normalbaselineskip\vskip-\footrulewidth
\hrule\@width\headwidth\@height\footrulewidth\vskip0.3\normalbaselineskip}}
\def\ps@fancy{
\let\@mkboth\markboth
\@ifundefined{chapter}{\def\sectionmark##1{\markboth
{\uppercase{\ifnum \c@secnumdepth>\z@
\thesection\hskip 1em\relax \fi ##1}}{}}
\def\subsectionmark##1{\markright {\ifnum \c@secnumdepth >\@ne
\thesubsection\hskip 1em\relax \fi ##1}}}
{\def\chaptermark##1{\markboth {\uppercase{\ifnum \c@secnumdepth>\m@ne
\@chapapp\ \thechapter. \ \fi ##1}}{}}
\def\sectionmark##1{\markright{\uppercase{\ifnum \c@secnumdepth >\z@
\thesection. \ \fi ##1}}}}
\def\@oddhead{\@fancyhead\relax\@olhead\@ochead\@orhead\hss}
\def\@oddfoot{\@fancyfoot\relax\@olfoot\@ocfoot\@orfoot\hss}
\def\@evenhead{\@fancyhead\hss\@elhead\@echead\@erhead\relax}
\def\@evenfoot{\@fancyfoot\hss\@elfoot\@ecfoot\@erfoot\relax}
\headwidth\textwidth}
\def\ps@fancyplain{\ps@fancy \let\ps@plain\ps@plain@fancy}
\def\ps@plain@fancy{\@fancyplaintrue\ps@fancy}
love-tex/lists.latex 100644 0 0 5376 5600705270 13111 0 ustar root root \setlength{\unitlength}{0.0125in}%
\begin{picture}(400,372)(20,460)
\thicklines
\put( 90,540){\line( 0,-1){ 20}}
\put(230,540){\line( 0,-1){ 40}}
\put(180,500){\framebox(100,40){}}
\put(180,520){\line( 1, 0){100}}
\put(370,540){\line( 0,-1){ 40}}
\put(320,500){\framebox(100,40){}}
\put(320,520){\line( 1, 0){100}}
\put(290,460){\framebox(100,20){}}
\put(340,480){\line( 0,-1){ 20}}
\put(110,530){\vector( 1, 0){ 70}}
\put(370,470){\vector( 0, 1){ 30}}
\put(250,510){\line( 1, 0){ 50}}
\put(300,510){\line( 0, 1){ 20}}
\put(300,530){\vector( 1, 0){ 20}}
\put( 50,525){\makebox(0,0)[lb]{\raisebox{0pt}[0pt][0pt]{\twlbf head}}}
\put(300,465){\makebox(0,0)[lb]{\raisebox{0pt}[0pt][0pt]{\twlbf tail}}}
\put(190,525){\makebox(0,0)[lb]{\raisebox{0pt}[0pt][0pt]{\twlbf val}}}
\put(330,525){\makebox(0,0)[lb]{\raisebox{0pt}[0pt][0pt]{\twlbf val}}}
\put(190,505){\makebox(0,0)[lb]{\raisebox{0pt}[0pt][0pt]{\twlbf next}}}
\put(330,505){\makebox(0,0)[lb]{\raisebox{0pt}[0pt][0pt]{\twlbf next}}}
\put(380,505){\makebox(0,0)[lb]{\raisebox{0pt}[0pt][0pt]{\twltt NULL}}}
\put(245,525){\makebox(0,0)[lb]{\raisebox{0pt}[0pt][0pt]{\twltt 5}}}
\put(385,525){\makebox(0,0)[lb]{\raisebox{0pt}[0pt][0pt]{\twltt 7}}}
\put( 40,780){\framebox(100,20){}}
\put( 90,800){\line( 0,-1){ 20}}
\put( 40,740){\framebox(100,20){}}
\put( 40,520){\framebox(100,20){}}
\put( 90,760){\line( 0,-1){ 20}}
\put( 20,820){\makebox(0,0)[lb]{\raisebox{0pt}[0pt][0pt]{\twlit Initially}}}
\put( 50,785){\makebox(0,0)[lb]{\raisebox{0pt}[0pt][0pt]{\twlbf head}}}
\put( 50,745){\makebox(0,0)[lb]{\raisebox{0pt}[0pt][0pt]{\twlbf tail}}}
\put(100,785){\makebox(0,0)[lb]{\raisebox{0pt}[0pt][0pt]{\twltt NULL}}}
\put(100,745){\makebox(0,0)[lb]{\raisebox{0pt}[0pt][0pt]{\twltt NULL}}}
\put( 40,660){\framebox(100,20){}}
\put( 90,680){\line( 0,-1){ 20}}
\put(230,680){\line( 0,-1){ 40}}
\put(180,640){\framebox(100,40){}}
\put(180,660){\line( 1, 0){100}}
\put(155,600){\framebox(100,20){}}
\put(205,620){\line( 0,-1){ 20}}
\put(110,670){\vector( 1, 0){ 70}}
\put(230,610){\vector( 0, 1){ 30}}
\put( 50,665){\makebox(0,0)[lb]{\raisebox{0pt}[0pt][0pt]{\twlbf head}}}
\put(165,605){\makebox(0,0)[lb]{\raisebox{0pt}[0pt][0pt]{\twlbf tail}}}
\put(190,665){\makebox(0,0)[lb]{\raisebox{0pt}[0pt][0pt]{\twlbf val}}}
\put(190,645){\makebox(0,0)[lb]{\raisebox{0pt}[0pt][0pt]{\twlbf next}}}
\put(240,645){\makebox(0,0)[lb]{\raisebox{0pt}[0pt][0pt]{\twltt NULL}}}
\put(245,665){\makebox(0,0)[lb]{\raisebox{0pt}[0pt][0pt]{\twltt 5}}}
\put( 20,700){\makebox(0,0)[lb]{\raisebox{0pt}[0pt][0pt]{\twlit After : }}}
\put( 55,700){\makebox(0,0)[lb]{\raisebox{0pt}[0pt][0pt]{\twltt tail=add\_list\_item(5);}}}
\put( 20,560){\makebox(0,0)[lb]{\raisebox{0pt}[0pt][0pt]{\twlit After :}}}
\put( 55,560){\makebox(0,0)[lb]{\raisebox{0pt}[0pt][0pt]{\twltt tail=add\_list\_item(7);}}}
\end{picture}
love-tex/part1.tex 100644 0 0 31553 5600705271 12502 0 ustar root root % Copyright (c) 1993 by T.P.Love. This document may be copied freely
% for the purposes of education and non-commercial research.
% Cambridge University Engineering Department,
% Cambridge CB2 1PZ, England.
\section{Introduction}
C's popularity has increased as Unix has become more widespread. It
is a flexible, concise and small language, with a mix of low-level
assembler-style commands and high-level commands. It's
much used with the ${\cal X}$ graphics system and increasingly for
numerical analysis.
The first {\em de facto} standard C was as described in \cite{KandR}
and is often known as \KandR\ . The current standard is \ANSI\
\cite{ansi} in which the source contained in this document is written.
It can be compiled on the {\tt HP} workstations using {\tt cc -Aa}.
To those who have programmed before, simple C programs shouldn't be too
hard to read. \label{DEMO1} Suppose you call this program {\tt basics.c}
\begin{verbatim}
#include
#include
int mean(int a,int b)
{
return (a + b)/2;
}
int main()
{
int i, j;
int answer;
/* comments are done like this */
i = 7;
j = 9;
answer = mean(i,j);
printf("The mean of %d and %d is %d\n", i, j, answer);
exit (0);
}
\end{verbatim}
Note that the source is free-format and case matters.
All C programs need a {\tt main} function where
execution begins. In this example some variables local to {\tt main} are
created and assigned (using `{\tt =}' rather than `{\tt :=}'. Also
note that `{\tt ;}' is a
statement terminator rather than a separator as it is in {\tt Pascal}). Then
a function {\tt mean} is called that calculates the mean of the arguments
given it.
The types of the formal parameters of the function (in this case {\tt a}
and {\tt b}) should be compatible with the actual parameters in the call.
The initial values
of {\tt a} and {\tt b} are copied from the variables mentioned in the
call ({\tt i and j}).
The function {\tt mean} returns the answer (an integer, hence the `{\tt int}'
before the function name), which is printed out using
{\tt printf}. The on-line manual page describes {\tt printf} fully.
For now, just note that the 1st argument to {\tt printf} is a string
in which is embedded format strings; {\tt \%d} for integers, {\tt \%f}
for floats and {\tt \%s} for strings. The variables that these format
strings refer to are added to the argument list of {\tt printf}. The
`\verb|\n|' character causes a carriage return.
C programs stop when
\begin{itemize}
\item The end of {\tt main} is reached.
\item An {\tt exit()} call is reached.
\item The program is interrupted in some way.
\item The program crashes
\end{itemize}
This program can be compiled using `{\tt cc -Aa -o basics basics.c}'. The {\tt `-o'}
option renames the resulting file {\tt basics} rather than the default
{\tt a.out}. Run it by typing `{\tt basics}'. A common mistake that beginners
make \marginpar{\Warning\ }
is to call their executable `{\tt test}'. Typing {\tt test} is likely to
run the {\tt test} facility built into the shell, producing no input,
rather than the user's program. This can be circumvented by typing
{\tt ./test} but one might just as well void program names that might be
names of unix facilities. If you're using the {\tt ksh} shell then typing
`{\tt whence {\em program\_name}}' will tell you whether there's already
a facility with that name.
\section{Compilation Stages}
\begin{figure}
\begin{center}
\input{comp.latex}
\end{center}
\caption{Compilation Stages}
\end{figure}
First the {\em Preprocessor} {\tt cpp} is run. This strips out comments and
interprets directives (lines with a `{\tt \#}' character in the first column).
The
`{\tt \#include}' directive inserts the named file into the source
code, looking for the file in the directory {\tt /usr/include}.
Include files have a `{\tt .h}' suffix by convention, and
shouldn't contain executable code, only definitions and declarations.
{\tt /usr/include/stdio.h} and {\tt /usr/include/stdlib.h} should always
be included. Other useful include files are {\tt /usr/include/limits.h}
and {\tt /usr/include/math.h} which define characteristics of
the machine and the maths implementation.
Further preprocessor directives to do with macros, etc, will be introduced
later. If you
want to see how the code looks after pre-processing, try typing
\begin{verbatim}
cc -Aa -E basics.c
\end{verbatim}
After the preprocessor comes the compiler, which after a pass or 2
produces assembler code. This is assembled to produce an object
file, in this case {\tt basics.o}.
Finally the link-loader produces the executable from the object file
and any other object you mention. The standard C
library is automatically consulted. Any other
libraries that your code needs have to be mentioned on the
compile line. \Eg , ending the line with `{\tt -lm}' links in
the maths library, `{\tt -lX11}' links in {\cal X} graphics functions.
Note that it's not sufficient to just have `\verb|#include
at the top of the file if you're doing maths. This just supplies
enough information so that the compiler can do its work correctly. It
doesn't tell the link-loader where the maths routines actually are. You
need to have `{\tt -lm}' on the command line before an executable
can be produced.
The stages of compilation can be seen if a `{\tt -v}' flag is given
to the compiler.
\section{Variables and Literals}
Variable names can't begin with a digit. Nor can they contain
operators (like `\verb|.|' or `\verb|-|').
They have to be declared before being used. The available scalar types
are {\tt char}, {\tt short}, {\tt int}, {\tt long}, {\tt float} and
{\tt double}. {\tt char}s and the various lengths of integers can be
{\tt signed} (the default) or {\tt unsigned}.
Often you don't explicitly have to convert types. If you operate on variables
of different types, type conversion takes place auomatically. \Eg\ if you add
an {\tt int}
and a {\tt float} then the {\tt int} will be converted to a {\tt float}
and the result will be a {\tt float}.
\begin{verbatim}
unsigned int i;
float f = 3.14;
i = f;
\end{verbatim}
will automatically set {\tt i} to 3, truncating the real value. To explicitly
convert types use {\em casting}; \Eg
\begin{verbatim}
i = (unsigned int) f;
\end{verbatim}
Most conversions preserve the numerical value but occasionally this is
not possible and overflow or loss of precision results. C won't warn you
if this happens.\marginpar{\Warning\ }
The length of an integer isn't the same on all machines.
`{\tt sizeof (int)}' will return the number of bytes used by an integer.
The scope of a variable is the block (the function, or \verb| { }| pair)
it's declared in, or the remainder of the file it's declared in.
Variables declared outside of a block and functions can be accessed from other
files unless they're declared to be {\tt static}.
Variables declared in functions can preserve their value between calls
if they are defined as {\tt static}, otherwise they're {\tt automatic},
getting recreated for each call of the function.
Character values can written in various ways :- \Eg\ on machines that
use {\tt ASCII}
\begin{verbatim}
'A' '\101' '\x41'
\end{verbatim}
all represent 65; the first using the ASCII {\tt A} character,
the second using octal and the third hexadecimal. The newline
character is \verb|'\n'|.
Integer and real values can be variously expressed:-
\begin{center}
\begin{tabular}{ll}
{\tt 15L} & long integer 15\\
{\tt 015} & octal integer 15\\
{\tt 0xF7} & Hex (base 16) number F7\\
{\tt 15.3e3} & $ 15.3 \times 10^3$, a float\\
{\tt 15.3e3L} & $ 15.3 \times 10^3$, a double\\
\end{tabular}
\end{center}
\section{Aggregates}
Variables of the same type can be put into arrays.
\begin{verbatim}
char letters[50];
\end{verbatim}
defines an array of 50 characters, {\tt letter[0]} being the 1st
and {\tt letter[49]} being the last character. C has no subscript
checking; if you go off the end of an array C won't warn you.\marginpar{\Warning\ }
Multidimensional arrays can be defined too. \Eg
\begin{verbatim}
char values[50][30][10];
\end{verbatim}
defines a 3D array. Note that you can't access an element using
\verb|values[3,6,1]|; you have to type \verb|values[3][6][1]|.
Variables of different types can be grouped into a {\em structure}
(like a {\tt record} in {\tt Pascal}).
\begin{verbatim}
struct person {
int age;
int height;
char surname[20];
} fred, jane;
\end{verbatim}
defines 2 structures of type {\tt person} each of 3 fields. Fields are
accessed using the `{\tt .}' operator. For example,
{\tt fred.age} is an integer which can be used in assignments
just as a simple variable can.
{\tt typedef} creates a new type. \Eg
\label{typedef}
\begin{verbatim}
typedef struct{
int age;
int height;
char surname[20];
} person;
\end{verbatim}
create a type called {\tt person} and
\begin{verbatim}
typedef struct{
double real;
double imaginary;
} complex;
\end{verbatim}
creates a {\tt complex} type. Note that {\tt typedef}
creates new variable types but doesn't create any new variables.
These are created just as variables of the predefined types are:-
\begin{verbatim}
person fred, jane;
\end{verbatim}
As you see, new variable types are easily produced. What you {\em can't}
do (but can in {\tt C++} and {\tt Algol68}) is extend the meaning of an
existing
operator (`overload' it) so that it works with the new variable type: you
have to write a specific function instead.
A {\tt union} is like a {\tt struct} except that the fields
occupy the same memory location with enough memory
allocated to hold the largest item. The programmer has to keep a note of
what the {\tt union} is being used for. \Eg\ after this code fragment runs
fred will be 163 years old.
\begin{verbatim}
...
union person {
int age;
int height;
char surname[20];
} fred;
fred.age = 23;
fred.height = 163;
printf("Fred is %d years old\n", fred.age);
...
\end{verbatim}
\section{Constructions}
C has the following loop and selection constructs:-
\subsection*{Selection}
\begin{verbatim}
...
if (i==3) /* checking for equality; `!=' tests for inequality */
/* no braces needed for a single statement */
j=4;
else{
/*the braces are necessary if the
clause has more than one statement
*/
j=5;
k=6;
}
...
\end{verbatim}
\begin{verbatim}
...
/* switch is like the case statement in pascal.
The values that the switching variable is compared with
have to be constants, or `default'.
*/
switch(i){
case 1: printf("i is one\n");
break; /* if break wasn't here, this case will
fall through into the next.
*/
case 2: printf("i is two\n");
break;
default: printf("i is neither one nor two\n");
break;
}
...
\end{verbatim}
\subsection*{Loops}
\begin{verbatim}
...
while(i<30){ /* test at top of loop */
something();
...
}
\end{verbatim}
\begin{verbatim}
...
do {
something();
} while (i<30); /* test at bottom of loop */
...
\end{verbatim}
The `{\tt for}' construction in C is very general. In its most common
form it's much like {\tt for} in other languages.
\begin{verbatim}
...
for(i=0; i<5; i=i+1){
something();
}
...
\end{verbatim}
\noindent The general form of `{\tt for}' is
\begin{verbatim}
for ([expression1]; [expression2]; [expression3])
something();
\end{verbatim}
where all the expressions are optional. The default value for
{\tt expression2} is {\tt 1} ({\tt true}). Essentially, the {\tt for} loop
is a {\tt while} loop. The above {\tt for} loop is equivalent to
\begin{verbatim}
...
expression1; /* initialisation */
while (expression2){ /* condition */
something();
expression3; /* code done each iteration */
};
...
\end{verbatim}
\Eg\ the 2 fragments below are equivalent. `{\tt i}' is set to 3, the
loop is run once for {\tt i=3} and once for {\tt i=4}, then iteration
finishes when {\tt i=5}.
\noindent{\begin{minipage}[t]{\minitw}
\begin{verbatim}
for (i = 3; i < 5; i=i+1)
total = total + i;
\end{verbatim}
\end{minipage} \ \hfill \
\begin{minipage}[t]{\minitw}
\begin{verbatim}
i = 3;
while(i < 5){
total = total + i;
i=i+1;
}
\end{verbatim}
\end{minipage}}
Within any of the above loop constructions, {\tt continue}
stops the current iteration and goes to the next and {\tt break}
stops the iterations altogether. \Eg\ in the following fragment
{\tt 0} and {\tt 2} will be printed out.
\begin{verbatim}
...
i=0;
while (i<5){
if (i==1){
i = i+1;
continue;
}
if (i==3)
break;
printf("i = %d\n", i);
i=i+1;
}
...
\end{verbatim}
If you want a loop which only ends when {\tt break} is done, you can
use `\verb|while(1)|' (because {\tt 1} being non-zero, counts as being true)
or `\verb|for(;;)|'.
The \verb| { }| symbols are used to compound statements. You can declare
variables at the start of any compound statement. For instance, if you're
worried about the scope of an index variable in a {\tt for} loop, you
could do the following.
\begin{verbatim}
{int i;
for (i=i;i<5;i++)
printf("i is %d\n",i);
}
\end{verbatim}
love-tex/part2.tex 100644 0 0 36661 5600705272 12511 0 ustar root root % Copyright (c) 1993 by T.P.Love. This document may be copied freely
% for the purposes of education and non-commercial research.
% Cambridge University Engineering Department,
% Cambridge CB2 1PZ, England.
\section{Contractions}
C veterans use abbreviated forms for expressions. Some are natural and
widely adopted, others merely lead to obscurity -- even if they produce
faster code (and often they don't) they waste future programmers'
time.
\begin{itemize}
\item {\tt i++} is equivalent to {\tt i=i+1}.
This (and the {\tt i--} decrementing operator) is a common
contraction. The operation can be done after the variable is used,
or (by using {\tt --i}, {\tt ++i}) before, so
\begin{verbatim}
...
i = 4;
printf("i = %d\n", i++)
...
\end{verbatim}
and
\begin{verbatim}
...
i = 4;
printf("i = %d\n", ++i)
...
\end{verbatim}
will both leave {\tt i} as {\tt 5}; but in the 1st fragment {\tt 4} will be
printed out while in the 2nd {\tt 5} will.
\item
{\tt i+=6} is equivalent to {\tt i=i+6}. This style of contraction isn't so common,
but can be used with most of the binary operators.
\item Assignment statements have a value; the final value of the left-hand-side, so
{\tt j = (i=3+4)} will set {\tt i} then {\tt j} to {\tt 7}, and
{\tt i = j = k = 0} will set {\tt k}, then {\tt j}, then {\tt i} to zero.
This feature should be used with caution.
\item The `{\tt ,}' operator is used between 2 expressions if the
value of the 1st expression can be ignored. It's a way to put 2 or
more statements
where normally only one would go. \Eg
\begin{verbatim}
for(init(3),i=0,j+0; i<100; i++,j++)
\end{verbatim}
This feature is often over-used too.
\item Expressions with comparison operators return {\tt 1} if the comparison
is true, {\tt 0} if false, so {\tt while(i!=0)} and {\tt while(i)} are
equivalent.
\item The {\tt `if (cond) exp1; else exp2'} construction can be abbreviated
using `{\tt (cond)?exp1: exp2}'. The following fragments are equivalent.
\begin{verbatim}
...
if (a==6)
j=7;
else
j=5;
...
(a==6)?j=7:j=5;
...
\end{verbatim}
This notation should be used with discretion.
\end{itemize}
\section{Functions}
C has no procedures, only functions. Their definitions can't be nested but all
except {\tt main} can be called recursively.
In \ANSI\ the form of a function definition is
\begin{flushleft}
{\em $<$function type$>$} {\em $<$function name$>$} {\tt (} {\em $<$formal argument list$>$} {\tt )}\\
{\tt \{}\\
{\em $<$local variables$>$}\\
$<$body$>$\\
{\tt \}}\\
\end{flushleft}
\Eg
\begin{verbatim}
int mean(int x, int y)
{
int tmp;
tmp = (x + y)/2;
return tmp;
}
\end{verbatim}
In \KandR\ the same function would be written as
\begin{verbatim}
int mean(x,y)
int x;
int y;
{
int tmp;
tmp = (x + y)/2;
return tmp;
}
\end{verbatim}
Note that the formal argument declarations are differently placed.
This are the most visible
difference between \ANSI\ and \KandR\ . Programs exist to convert
between the 2 forms of formal argument declaration (see the
`{\tt comp.lang.c}' newsgroup for details).
The default function type is `{\tt extern int}' and the default type for
the formal arguments is `{\tt int}' but depending on these defaults is asking for
trouble; they should be explicitly declared.
Functions end when
\begin{itemize}
\item execution reaches the closing `{\tt \}}' of the function. If the
function is supposed to return something, the return value will
be undefined.
\item a `{\tt return}' statement is reached, returning control to the
calling function.
\item an `{\tt exit}' statement is reached, ending execution of the
whole program.
\end{itemize}
Just as {\tt return} can return a value to the calling routine, so
{\tt exit} returns a value to the {\tt Unix} environment. By convention,
returning a zero means that the program has run successfully.
All parameters in C are `passed by value'. To performed the equivalent
of {\tt Pascal}'s `pass by reference' you need to know about pointers.
\section{Pointers}
Even if you don't use pointers yourself, the code you'll learn from
will have them. Suppose {\tt i} is an integer. To find the address of {\tt i}
the {\tt \&} operator is used ({\tt \&i}). Setting a pointer to this value
lets you refer indirectly to the variable {\tt i}. If you have the address of
a pointer variable and want to find the variable's value, then the
dereferencing operator {\tt *} is used.
\begin{verbatim}
...
int i;
/* The next statement declares i_ptr to be a pointer at
an integer. The declaration says that if i_ptr is
dereferenced, one gets an int.
*/
int *i_ptr;
i_ptr = &i; /* initialise i_ptr to point to i */
/* The following 2 lines each set i to 5 */
i = 5;
*iptr = 5;
\end{verbatim}
A pointer-to-an-{\tt int} has type {\tt int*} and is of a different type
to a pointer-to-a-{\tt char} (which has type {\tt char*}). The difference
matters especially when the pointer is being incremented; the
value of the pointer is increased by the size of the object it
points to. In the following fragment, the pointer steps through an array.
\begin{verbatim}
...
int numbers[10];
int *iptr;
int i;
numbers[0] = 1;
numbers[1] = 2;
numbers[2] = 3;
iptr = &numbers[0]; /* Point iptr to the first element in numbers[] */
/* now increment iptr to point to successive elements */
for (i=0; i<3; i++){
printf("*iptr is %d\n", *iptr);
iptr= iptr+1;
}
...
\end{verbatim}
Pointers are especially useful when functions operate on
structures. Using a pointer avoids copies of potentially
big structures being made.
\begin{verbatim}
typedef struct {
int age;
int height;
char surname[20];
} person;
person fred, jane;
int sum_of_ages(person *person1, person *person2){
int sum; /* a variable local to this function. */
/* Dereference the pointers, then use the `.' operator to get the
fields */
sum = (*person1).age + (*person2).age;
return sum;
}
\end{verbatim}
Operations like \verb|(*person1).age| are so common that there's a special,
more natural notation for it: \verb|person1->age|.
To further illustrate the use of pointers let's suppose that in the first
example on page \pageref{DEMO1} we wanted to pass to the function {\tt mean}
the variable
where we wanted the answer stored. Since we no longer need {\tt mean}
to return a value, we can make it return {\tt void}. Let's first try:-
\begin{verbatim}
#include
#include
void mean(int a, int b, int return_val )
{
return_val = (a + b)/2;
printf("return_val in mean in %d\n",return_val);
}
main()
{
int i, j;
int answer;
i = 7;
j = 9;
mean(i,j, answer);
printf("The mean of %d and %d is %d\n", i, j, answer);
}
\end{verbatim}
This won't work. Although {\tt return\_val} is set to the right value in
{\tt mean},
{\tt answer} isn't. Remember, {\tt return\_val} and {\tt answer} are
separate variables. The value of {\tt answer} is copied into {\tt return\_val}
when {\tt mean} is called. The {\tt mean} function doesn't know where
{\tt answer} is stored, so it can't change it. A pointer to
{\tt answer} has to be given to {\tt mean()}.
\begin{verbatim}
#include
#include
/* Note the form of the ptr_to_answer declaration below. It
says that if you dereference ptr_to_answer you get an
int. i.e. ptr_to_answer is a pointer to an int.
*/
void mean(int a,int b, int *ptr_to_answer)
{
*ptr_to_answer = (a + b)/2;
}
main()
{
int i, j;
int answer;
i = 7;
j = 9;
mean(i,j, &answer); /* Note that now we're passing a pointer
* to 'answer'
*/
printf("The mean of %d and %d is %d\n", i, j, answer);
}
\end{verbatim}
There's a special value for null pointers ({\tt NULL}) and a special
type for generic pointers ({\tt void*}). In \KandR\ , casting a
pointer from one type to another didn't change its value. In \ANSI\
however, alignment is taken into account. If a {\tt long} can only
begin at an even memory location, then a pointer of type {\tt char*}
pointing to an odd location will have its value changed if cast into
a {\tt long*}.
\section{Strings}
In C a string is just an array of characters. The end of the string is
denoted by a zero byte. The various string manipulation functions are
described in the online manual page called `{\tt string}', and
declared in the {\tt string.h} include file. The following piece of
code illustrates their use and highlights some problems
\label{DEMO2}
\begin{verbatim}
/* strings.c */
#include
#include
char str1[10]; /* This reserves space for 10 characters */
char str2[10];
char str3[]= "initial text"; /* str3 is set to the right size for you
* and automatically terminated with a 0
* byte. Note that you can only initialise
* strings this way when defining
*/
char *c_ptr; /* declares a pointer, but doesn't initialise it. */
unsigned int len;
main()
{
/* copy "hello" into str1. If str1 isn't big enough, hard luck */
strcpy(str1,"hello");
/* if you looked at memory location str1 you'd see these byte
values: 'h','e','l','l','o','\0'
*/
/* concatenate " sir" onto str1. If str1 isn't big enough, hard luck */
strcat(str1," sir");
/* values at str1 : 'h','e','l','l','o',' ','s','i','r','\0'
*/
len = strlen(str1); /* find the number of characters */
printf("Length of <%s> is %d characters\n", str1, len);
if(strcmp(str1, str3))
printf("<%s> and <%s> are different\n", str1, str3);
else
printf("<%s> and <%s> are the same\n", str1, str3);
if (strstr(str1, "boy") == (char*) NULL)
printf("The string
else
printf("The string
/* find the first `o' in str1 */
c_ptr = strchr(str1,'o');
if (c_ptr == (char*) NULL)
printf("There is no o in <%s>\n", c_ptr);
else{
printf("<%s> is from the first o in <%s> to the end of the string\n",
c_ptr, str1);
/* Now copy this part of str1 into str2 */
strcpy(str2, c_ptr);
}
}
\end{verbatim}
Usually `{\tt str1}' would be used instead of `\verb|&str1[0]|' to
refer to the address of the first element of the character array,
since C defines the value of an array name to be the location of
the first element. In fact, once you've set {\tt c\_ptr} to {\tt str},
the 2 variables behave similarly in {\em most} circumstances.
\begin{itemize}
\item
There is not really any difference in the behaviour of the {\em array
subscripting} operator {\tt []} as it applies to arrays and pointers.
The expressions \verb|str[i]| and \verb|c_ptr[i]| are both processed
internally using pointers. For instance, \verb|str[i]| is equivalent to
\verb|*((str)+(i))|.
\item
Array and pointer declarations are interchangeable as function formal
parameters. Since arrays decay immediately into pointers, an array is never
actually passed to a function. Therefore, any parameter
declarations which `look like' arrays, e.g.
\begin{verbatim}
int f(char a[])
{
...
}
\end{verbatim}
are treated by the compiler as if they were pointers, so `{\tt char a[]}'
could be replaced by `{\tt char* a}'.
This conversion holds {\em only} within function formal parameter
declarations, nowhere else. If this conversion bothers you, avoid
it.
\end{itemize}
Because the distinction between pointers and arrays often doesn't seem to
matter, programmers get surprised when it does. \label{EQUIVPTRS}
Arrays are not pointers. The array
declaration `\verb|char str1[10];|' requests that space for ten characters be
set aside. The pointer
declaration `\verb|char *c_ptr;|' on the other hand, requests a place
which
holds a pointer. The pointer is to be known by the name \verb|c_ptr|, and
can point to any {\tt char} (or contiguous array of {\tt char}s)
anywhere. {\tt str1} can't be changed: it's where the array begins and where
it will always stay.
You can't pass whole arrays to functions, only pointers to them. To declare
such pointers correctly you need to be aware of the different ways
that multi-demensional arrays can be stored in memory. Suppose you created
a 2D array of characters as follows:-
\begin{verbatim}
fruits[3][10] = {"apple", "banana", "orange"};
\end{verbatim}
This creates space for 3 strings each 10 bytes long. Let's say that
`{\tt fruits}' gets stored at memory location {\tt 6000}. Then this will
be the layout in memory:
\begin{verbatim}
6000 a p p l e \0 . . . .
6010 b a n a n a \0 . . .
6020 o r a n g e \0 . . .
\end{verbatim}
If you wanted to write a function that printed these strings out
so you could do `{\tt list\_names(fruits)}', the following routine
will work
\begin{verbatim}
void list_names(char names[][10] ){
int i;
for (i=0; i<3; i++){
printf("%s\n", names[i]);
}
}
\end{verbatim}
The routine {\em has} to be told the size of the things that
{\tt names} points to, otherwise it won't be able to
calculate {\tt names[i]} correctly. So the `{\tt 10}' needs
to be provided in the declaration. It doesn't care about how many things
there are in the
array, so the first pair of brackets might just as well be empty.
An equivalent declation is
\begin{verbatim}
void list_names(char (*names)[10]
\end{verbatim}
saying that `{\tt names}' is a pointer to an array each of
whose elements is 10 chars.
The above method wastes a lot of space if the strings differ greatly
in length. An alternative way to initialise names is as follows:-
\begin{verbatim}
char *veg[] = {"artichoke", "beetroot", "carrot"};
\end{verbatim}
Here `{\tt veg}' is set up as an array of {\tt pointer-to-char}s. The layout
in memory is different too. A possible layout is:-
\begin{verbatim}
Address Value
6000 9000
6004 9600
6008 9700
...
9000 a r t i c h o k e \0
9600 b e e t r o o t \0
9700 c a r r o t \0
\end{verbatim}
Note that `{\tt veg}' is the start of an array of pointers. The
actual characters are stored somewhere else. If we wanted a
function that would print out these strings, then the
`{\tt list\_names()}' routine above wouldn't do, since this
time the argument `{\tt names}' wouldn't be pointing to
things that are 10 bytes long, but 4 (the size of a {\tt pointer-to-char}).
The declaration needs to say that `{\tt names}' points to a character
pointer.
\begin{verbatim}
void list_names(char **names){
int i;
for (i=0; i<3; i++){
printf("%s\n", names[i]);
}
}
\end{verbatim}
The following declaration would also work:-
\begin{verbatim}
void list_names(char *names[]){
\end{verbatim}
Using {\tt cdecl} (see page \pageref{CDECL}) will help clarify the
above declarations.
The program below shows the 2 types of
array in action. The functions to print the names out are like the
above except that
\begin{itemize}
\item The arrays are endstopped so that
the functions needn't know beforehand how many elements are in
the arrays.
\item The {\tt for} loop uses some common contractions: \Eg\ {\tt
list\_names2}
stops when {\tt *names} is non-zero ({\it i.e.} non-{\tt NULL}).
\end{itemize}
\label{ARRAY_DEMO}
\begin{verbatim}
#include
#include
void list_names(char (*names)[10] ){
for (; names[0][0]; names++){
printf("%s\n", *names);
}
}
void list_names2(char *names[] ){
for (; *names; names++){
printf("%s\n",*names);
}
}
int main(int argc, char *argv[]){
char fruits[4][10] = {"apple", "banana", "orange", ""};
char *veg[] = {"artichoke", "beetroot", "carrot", (char*) NULL};
list_names(fruits);
list_names2(veg);
exit(0);
}
\end{verbatim}
love-tex/part3.tex 100644 0 0 120140 5600705274 12516 0 ustar root root % Copyright (c) 1993 by T.P.Love. This document may be copied freely
% for the purposes of education and non-commercial research.
% Cambridge University Engineering Department,
% Cambridge CB2 1PZ, England.
\section{Keywords, Operators and Declarations}
\subsection{Keywords}
You can't use the following reserved words for variable names, etc.
\begin{center}
{\tt
\begin{tabular}{lllll}
auto & break & case & char & const \\
continue & default & do & double & else \\
enum & extern & float& for & goto \\
if & int & long & register & short \\
signed & sizeof & static & struct & switch \\
typedef & union & unsigned & void & volatile \\
while & & & &
\end{tabular}
} % end tt
\end{center}
A few of these haven't yet been described.
\begin{description}
\item[auto]:- This is the default {\em Storage Class} for variables
so it's not explicitly used. {\tt static}, which you've already met,
is an alternative class.
\item[const]:- If a variable isn't meant to change you can define it
as {\tt const}. \Eg , If you create an integer using `{\tt const int i = 6;}'
then a later `{\tt i = 7;}' will be illegal. However, if you create a
pointer to {\tt i} and use this to change the value, you'll probably
get away with it. The main purpose of {\tt const} is to help optimisers.
{\tt volatile} is the opposite of {\tt const}.
\item[enum]:- C has enumerated types, like {\tt pascal}. \Eg
\begin{verbatim}
enum color {Red, Green, Blue};
\end{verbatim}
They're not as useful as in {\tt pascal} because C doesn't check if
you set an enumerated type to a valid value.
\item[register]:- You can suggest to the compiler that a variable
should be kept in a register for faster access. \Eg\ `{\tt register int i}'
might help if {\tt i} is a much-used indexing variable. An optimising
compiler should use registers efficienty anyway. You can't use
the `{\tt \&}' operator on a {\tt register} variable.
\end{description}
\subsection{Operators}
At last, here is a table of operators and precedence.
The lines of the table are in order of precedence, so
`{\tt a * b + 6}' is interpreted as `{\tt (a * b) + 6}'.
When in doubt put brackets in!
The {\bf Associativity} column shows how the operators group. \Eg
`{\tt $<$}' groups {left to right}, meaning that {\tt $a equivalent to {\tt $(a < b) < c$} rather than {\tt $a < (b < c)$}.
Both are pretty useless expressions.
\begin{center}
\begin{tabular}{|l|l|}\hline
\bf Associativity & \bf Operator\\\hline
left to right & \verb+() [], ->, .+\\
right to left & the unary operators \verb|!| (negation), \verb|~| (bit-not),
\verb|++, --, -, *, &, sizeof|\\
right to left & cast \verb|(type)|\\
left to right & \verb|*, /, % (modulus)|\\
left to right & \verb|- +|\\
left to right & \verb+<<, >>+\\
left to right & \verb+<, <=, >, >=+\\
left to right & \verb+==, != +\\
left to right & \verb+&+ (bit-and), \verb+|+ (bit-or)\\
left to right & \verb+^+ (bit-xor)\\
left to right & \verb+&&+ (logical and)\\
left to right & \verb+||+ (logical or)\\
right to left & \verb+?:+\\
right to left & \verb|=, +=, -=, /=, %=, >>=, &=|\\
left to right & \verb|,|\\\hline
\end{tabular}
\end{center}
\subsection*{Bit operations}
C can be used to operate on bits. This is useful for low-level
programming though the operations are also used when writing $\cal X$
graphics applications.
\begin{description}
\item[Setting a bit :- ]
Suppose you wanted to set bit 6 of {\tt i} (a {\tt long}, say) to
{\tt 1}. First you need to create a {\em mask} that has a {\tt 1} in
the 6th bit and {\tt 0} elsewhere by doing `\verb|1L<<6|'
which shifts all the bits of the {\tt long} {\tt 1} left 6
bits. Then you need to do a bit-wise {\tt OR} using
`\verb?i = i | (1L<<6)?'.
\item[Unsetting a bit :- ]
Suppose you wanted to set bit 6 of {\tt i} (a {\tt long}, say) to
{\tt 0}. First you need to create a {\em mask} that has a {\tt 0} in
the 6th bit and {\tt 1} elsewhere by doing `\verb|1L<<6|' then inverting
the bits using the \verb|~| operator. Then you need to do a bit-wise
{\tt AND} using the \verb|&| operator. The whole operation is
`\verb|i =i & ~(1<<6)|' which can be contracted to `\verb|i &= ~(1<<6)|'.
\item[Creating a mask for an $\cal X$ call :- ]
In $\cal X$ graphics, masks are often created each of whose bits represent a
option that is to be selected in some way. Each bit can be referred to
using an alias that has been set up in an include file. \Eg\ a mask
which could be used in a call to make a window sensitive to keypresses,
key releases and buttonpresses could be set up by doing
\begin{verbatim}
unsigned int mask = KeyPressMask | KeyReleaseMask | ButtonPressMask;
\end{verbatim}
\end{description}
\subsection{Declarations}
First, a note on terminology. A variable is {\em defined} when it is
created, and space is made for it. A variable is {\em declared}
when it already exists but needs to be re-described to the compiler
(perhaps because it was {\em defined} in another source file).
Think of {\em declaring} in C like {\em declaring} at customs --
admitting to the existence of something.
C declarations are not easy to read.
Any good book on C should explain how to read complicated C
declarations ``inside out'' to understand them, starting at the
variable name and working outwards back to the base type.
You shouldn't need to use complicated declarations so don't worry to
much if you can't `decode' them. Keep a cribsheet of useful {\tt typedef}s
and play with {\tt cdecl} (see section \ref{CDECL}).
\ANSI\ introduced the use of the `{\tt void}' keyword in various
contexts.
\begin{itemize}
\item `{\tt routine(void)}' -- the routine takes no arguments.
\item `{\tt void routine
(int i)}' -- the routine returns no arguments.
\item `{\tt void *ptr}' -- {\tt ptr} is a generic pointer which should
be cast into a specific form before use.
\end{itemize}
The following examples show common declarations.
\begin{small}
\begin{center}
\begin{tabular}{|l|l|}\hline
{\tt int *p} & pointer to an int\\
{\tt int x[10]} & an array of 10 ints\\
{\tt int (*x)[10]} & a pointer to an array of 10 ints\\
{\tt int *x[10]} & array of 10 pointers to ints\\
{\tt int (*f)(int)} & pointer to a function taking and returning an int\\
{\tt void (*f)(void)} & pointer to a function taking no args and returning nothing\\
{\tt int (*f[])(int)} & An array of pointers to a functions taking and returning an int\\\hline
\end{tabular}
\end{center}
\end{small}
Note the importance of the brackets in these declarations. If a
declaration gets too complex it should be broken down. For example, the
last example could be rewritten as
\begin{verbatim}
typedef int (*PFI)(int) /* declare PFI as pointer to function that
takes and returns an int.*/
PFI f[];
\end{verbatim}
\section{Memory Allocation}
Space is automatically set aside for variables when they are defined, but
sometimes you don't know beforehand how many variables you'll need or
just how long an array might need to be. The {\tt malloc} command
creates space, returning a pointer to this new area. To illustrate its
use and dangers, here's a sequence of attempts at writing a string
reverser program.
\begin{verbatim}
#include
#include
print_reverse(char *str)
{
int i;
unsigned int len;
len = strlen(str) - 1; /* Why the -1? Because if a string has n chars, the
last char will be at position n-1
*/
for (i=len; i>=0; i--)
putchar(str[i]);
}
void main()
{
char input_str[100] /* why 100? */
printf("Input a string\n");
gets(input_str); /* should check return value */
printf("String was %s\n", input_str);
print_reverse(input_str);
}
\end{verbatim}
This works, but is a bit `loose' (suppose the user types more than
100 characters?) and doesn't keep a copy of the
reversed string should it be needed later. The next example shows
a wrong (but not uncommon) attempt to solve this limitation.
\begin{verbatim}
#include
/* WRONG! */
char* make_reverse(char *str)
{
int i, j;
unsigned int len;
char newstr[100];
len = strlen(str) - 1;
j=0;
for (i=len; i>=0; i--;)
newstr[j] = str[i];
j++;
/* now return a pointer to this new string */
return newstr;
}
void main()
{
char input_str[100]; /* why 100? */
char *c_ptr;
printf("Input a string\n");
gets(input_str); /* should check return value */
c_ptr = make_reverse(input_str);
printf("String was %s\n", input_str);
printf("Reversed string is %s\n", c_ptr);
}
\end{verbatim}
Like many flawed C programs this will work much of the time, especially if
it's not part of a bigger program. The problems are that :-
\begin{itemize}
\item The memory allocated for {\tt newstr} when it was declared as an
`automatic' variable in {\tt make\_reverse} isn't permanent -- its lifetime
is just the time {\tt make\_reverse()} takes to execute. However, the
array's contents aren't erased, they're just freed for later use, so if you
access the array from outside {\tt make\_reverse} you might still get away
with it for a while. Making {\tt newstr} a {\tt static} will preserve the
data but only until it's overwritten by a subsequent call.
\item The newly created array of characters, {\tt newstr}, isn't terminated
with a zero character, \verb|`\0'|, so trying to print the characters out
as a string may be disastrous. `Luckily' the memory location that should
have been set to zero is likely to be zero anyway.
\end{itemize}
Let's try again.
\label{DEMO3}
\begin{verbatim}
/* mallocing.c */
#include
#include
char* make_reverse(char *str)
{
int i;
unsigned int len;
char *ret_str, *c_ptr;
len = strlen(str);
/* Create enough space for the string AND the final \0.
malloc returns a void*, so the results needs to be
cast into the right form.
*/
ret_str = (char*) malloc(len +1);
/*
Now ret_str points to a `permanent' area of memory.
*/
/* Point c_ptr to where the final '\0' goes and put it in */
c_ptr = ret_str + len;
*c_ptr = '\0';
/* now copy characters from str into the newly created space.
The str pointer will be advanced a char at a time,
the cptr pointer will be decremented a char at a time.
*/
while(*str !=0){ /* while str isn't pointing to the last '\0' */
c_ptr--;
*c_ptr = *str;
str++; /* increment the pointer so that it points to each
character in turn. */
}
return ret_str;
}
void main()
{
char input_str[100]; /* why 100? */
char *c_ptr;
printf("Input a string\n");
gets(input_str); /* Should check return value */
c_ptr = make_reverse(input_str);
printf("String was %s\n", input_str);
printf("Reversed string is %s\n", c_ptr);
}
\end{verbatim}
The {\tt malloc}'ed space will be preserved until it is explicitly
freed (in this case by doing `{\tt free(c\_ptr)}'). Note that the pointer
to the {\tt malloc}'ed space is the
only way you have to access that memory: lose it and the memory
will be inaccessible.
{\tt malloc} is often used to create tree and list structures, since
one often doesn't know beforehand how many items will be needed.
See section \ref{LINKEDLIST} for an example.
\section{Input/Output}
\subsection{File I/O under Unix}
Some file operations work on {\em file pointers} (buffered) and some
lower level ones use small integers called {\em file descriptors} (an index
into a table of information about opened files).
The following code doesn't do anything useful but it does use most
of the file handling routines. The manual pages describe how each
routine reports errors. If {\tt errnum} is set on error then {\tt perror}
can be called to print out the error string corresponding to the error
number, and a string the programmer provides as the argument to {\tt perror}.
\label{DEMO4}
\begin{verbatim}
#include
#include
#include
#include
#include
include files need to be mentioned */
#define TRUE 1
int bytes_read;
size_t fp_bytes_read;
int fd; /* File descriptors */
int fd2;
FILE *fp; /* File pointers */
FILE *fp2;
char buffer[BUFSIZ]; /* BUFSIZ is set up in stdio.h */
main(){
/* Use File descriptors - unbuffered */
fd = open ("/etc/group", O_RDONLY);
if (fd == -1){
perror("Opening /etc/group");
exit(1);
}
while (TRUE){
bytes_read = read (fd, buffer,BUFSIZ);
if (bytes_read>0)
printf("%d bytes read from /etc/group.\n", bytes_read);
else{
if (bytes_read==0){
printf("End of file /etc/group reached\n");
close(fd);
break;
}
else if (bytes_read == -1){
perror("Reading /etc/group");
exit(1);
}
}
}
/* now use buffering */
fp = fopen("/etc/passwd","r");
if (fp == NULL){
printf("fopen failed to open /etc/passwd\n");
exit(1);
}
while(TRUE){
fp_bytes_read= fread (buffer, 1, BUFSIZ, fp);
printf("%d bytes read from /etc/passwd.\n", fp_bytes_read);
if (fp_bytes_read==0)
break;
}
rewind(fp); /* go back to the start of the file */
/* Find the descriptor associated with a stream */
fd2 = fileno (fp);
if (fd2 == -1)
printf("fileno failed\n");
/* Find the stream associated with a descriptor */
fp2 = fdopen (fd2, "r");
if (fp2 == NULL)
printf("fdopen failed\n");
fclose(fp2);
}
\end{verbatim}
To take advantage of unix's I/O redirection it's often useful to write
filters: programs that can read from {\tt stdin} and write to {\tt stdout}.
In Unix, processes have {\tt stdin}, {\tt stdout} and {\tt stderr}
channels. In {\tt stdio.h}, these names have been associated with
file pointers. The following program
reads lines from {\tt stdin} and writes them to {\tt stdout}
prepending each line by a line number. Errors are printed on {\tt stderr}.
{\tt fprintf} takes the same arguments as {\tt printf} except that you
also specify a file pointer. {\tt fprintf(stdout,....)} is equivalent to
{\tt printf(....)}.
\label{LINE_NUMS}
\begin{verbatim}
/* line_nums.c
Sample Usage : line_nums < /etc/group
*/
#include
#include
#define TRUE 1
int lineno = 0;
int error_flag = 0;
char buf[BUFSIZ]; /* BUFSIZ is defined in stdio.h */
main(){
while(TRUE){
if (fgets(buf,BUFSIZ, stdin) == NULL){
if (ferror(stdin) != 0){
fprintf(stderr,"Error during reading\n");
error_flag = 1;
}
if (feof(stdin) != 0)
fprintf(stderr,"File ended\n");
clearerr(stdin);
break; /* exit the while loop */
}
else{
lineno++;
/* in the next line, "%3d" is used to restrict the
number to 3 digits.
*/
fprintf(stdout,"%3d: ", lineno);
fputs(buf, stdout);
}
}
fprintf(stderr,"%d lines written\n", lineno);
exit(error_flag);
}
\end{verbatim}
{\tt ferror()} and {\tt feof()} are intended to clarify ambiguous
return values. Here that's not a problem since a {\tt NULL} return
value from {\tt fgets()} can only mean end-of-file, but with for
instance {\tt getw()} such double checking is necessary.
\subsection{Interactive}
\subsubsection{Output}
For efficiency, writing to files under Unix is usually buffered, so
{\tt printf(....)} might not immediately produce bytes at {\tt stdout}.
If you want to force synchronous output you can
\begin{itemize}
\item Use {\tt stderr} (which is usually unbuffered) instead of {\tt stdout}.
\item Use {\tt fflush(stdout)} to flush out the standard output buffer.
\item Use {\tt setbuf(stdout,NULL)} to stop standard output being buffered.
\end{itemize}
\subsubsection{Input}
{\tt scanf} is a useful-looking routine for getting input.
It looks for input of the format described in its 1st argument
and puts the input into the variables pointed to by the succeeding
arguments. It returns the number of arguments successfully read.
Suppose you wanted the user to type their surname then their age in. You could
do this:-\marginpar{\Warning\ }
\begin{verbatim}
int age;
char name[50];
int return_val;
main(){
printf("Type in your surname and age, then hit the Return key\n");
while(TRUE){
return_val= scanf("%s %d", name, &age);
if (return_val == 2)
break;
else
printf("Sorry. Try Again\n");
}
}
\end{verbatim}
If you use {\tt scanf} in this way to directly get user input, and
the user types in something different to what {\tt scanf()} is expecting,
it goes wrong because {\tt scanf} keeps reading until its entire input list
is fulfilled or {\tt EOF} is reached. It treats a newline as {\em white
space}. Thus users can become very frustrated in this example if, say, they
keep typing their name, then hitting {\em Return}.
A better scheme is to store user input in an intermediate
string and use {\tt sscanf()}, which is like {\tt scanf()} except that its
first argument is the string which is to be scanned. \Eg\ in
\begin{verbatim}
...
int ret, x, y, z;
ret = sscanf(str,"x=%d y=%d z=%d", &x, &y, &z);
...
\end{verbatim}
{\tt sscanf}, given a string `{\tt x=3 y=7 z=89}', will set the
{\tt x}, {\tt y}, and {\tt z} values accordingly and {\tt ret} will be
set to {\tt 3} showing that 3 values have been scanned. If {\tt str}
is `{\tt x+1 y=4}', {\tt sscanf} will return 2 and won't hang.
To read the original string in,
{\tt fgets()} is a safer routine to use than {\tt gets()} since with
{\tt gets()} one can't check to see if the input line is too large for
the buffer. This still leaves the problem that the string
may contain a newline character (not just whitespace) when using {\tt fgets}.
One must make
annoying provisions for ends of lines that are not necessary
when input is treated as a continuous stream of characters.
\section{Source File organisation}
The needs of large-scale organisation and support for many
platforms may make modules incomprehensible unless some
understanding of the overall structure is gained first.
\subsection{Preprocesser Facilities}
The preprocessor has some useful options.
\begin{description}
\item[sourcefile inclusion :- ] \hspace{0cm}
\begin{verbatim}
#include "defines.h"
...
#include
\end{verbatim}
The difference between these two variants is that with the included file
in quotes, it is first looked for in the directory of the source file.
In each case, the standard include directories on the system are
searched as well as any directories mentioned on the command line
after the `{\tt -I}' flag. See the `{\tt cpp}' man page for more details.
\item[macro replacement :- ] \hspace{0cm}
Note that these macros are expanded before the compiler is called.
They aid legibility. In the first example below, a simple substitution is
done. In the second, an in-line macro is defined, whose execution should
be faster than the equivalent function.
\begin{verbatim}
#define ARRAY_SIZE 1000
char str[ARRAY_SIZE];
...
#define MAX(x,y) ((x) > (y) ? (x) : (y))
int max_num;
max_num = MAX(i,j);
...
\end{verbatim}
\item[conditional inclusion :- ] \hspace{0cm}
Blocks of code can be conditionally compiled according to the
existence or value of a preprocessor variable. A variable can
be created using the `\verb|#define|' preprocessor directive or
using the `{\tt -D}' option at compilation time.
\begin{verbatim}
#define DEBUG
#ifdef DEBUG
printf("got here\n");
#else
something();
#endif /*DEBUG*/
...
#if 0
/* this code won't reach the compiler */
printf("got here\n");
#endif
\end{verbatim}
\end{description}
\subsection{Multiple Source Files}
Modularisation not only makes the source more easy to manage but it
speeds up re-compilation: you need only recompile the changed source
files. Also, by keeping the {\tt I/O} components in one file (and
perhaps the text to be printed into another) one can more easily convert
the software
to run on other machines and in other natural languages.
By default, functions and variables defined outside of functions
can be accessed from other files, where they should be declared
using the {\tt extern} keyword. If however the variable is defined as
{\tt static}, it can't be accessed from other files. In the following
example, `{\tt i}', `{\tt j}' and the function `{\tt mean}' are created
in {\tt file1.c} but only `{\tt i}' can be accessed from {\tt file2.c}.
\noindent{\begin{minipage}[t]{\minitw}
\begin{verbatim}
/* file1.c */
int i;
static int j;
static int mean(int a, int b){
...
\end{verbatim}
\end{minipage} \ \hfill \
\begin{minipage}[t]{\minitw}
\begin{verbatim}
/* file2.c */
extern int i;
\end{verbatim}
\end{minipage}}
Names of external variables should be kept short; only the first 6 initial
characters are guaranteed to be significant (though in practise the
first 255 character often are).
You should keep to a minimum the number of global variables.
You can use \verb|include| files to manage your global variables.
\begin{enumerate}
\item Construct a `{\tt globals.h}' file with all of your
\verb|#define|s and variable
declarations in it. Make sure all variables are defined as {\tt extern}s.
Include this file in all the relevant source files.
\item In the file that contains your {\tt main()}, you again have all the
variable
definitions, minus the {\tt externs}. This is important -- if they are
all defined {\tt extern}, the linker will not be able to allocate memory for
them.
\end{enumerate}
You can achieve this with the help of the pre-processor if your
{\tt globals.h} looks like this:-
\begin{verbatim}
#ifdef LOCAL
#define EXTERN
#else
#define EXTERN extern
#endif
EXTERN int num_of_files;
..
\end{verbatim}
In this way, the `{\tt EXTERN}' becomes `{\tt extern}' in every file that
includes {\tt globals.h}. The trick is then to have
\begin{verbatim}
#define LOCAL
#include "globals.h"
\end{verbatim}
in the file containing the {\tt main} routine.
If you're calling a routine in one file from another file it's all the
more important for the formal parameters to be declared correctly.
Note especially that the declaration `{\tt extern char *x}' is not the
same as `{\tt extern char x[]}' -- one is of type `{\tt pointer-to-char}'
and the other is `{\tt array-of-type-char}' (see section \ref{EQUIVPTRS}).
\subsection{Make}
If you have many source files you don't need to recompile them all if
you only change one of them. By writing a {\tt makefile} that describes
how the executable is produced from the source files, the {\tt make}
command will do all the work for you.
The following makefile says that {\tt pgm} depends on two files
{\tt a.o} and {\tt b.o}, and that they in turn depend on their
corresponding source files ({\tt a.c} and {\tt b.c)} and a common
file {\tt incl.h}:
\begin{verbatim}
pgm: a.o b.o
cc -Aa a.o b.o -o pgm
a.o: incl.h a.c
cc -Aa -c a.c
b.o: incl.h b.c
cc -Aa -c b.c
\end{verbatim}
Lines with a `{\tt :}' are of the form
\begin{verbatim}
target : dependencies
\end{verbatim}
{\tt make} updates a target only if it's older than a file it depends on.
The way that the target should be updated is
described on the line following the dependency line (Note: this line needs
to begin with a {\tt TAB} character).
Here's a more complex example of a {\tt makefile}
for a program called {\tt dtree}. First some variables are created and
assigned.
In this case typing `{\tt make}' will attempt to recompile the {\tt dtree}
program (because the default target is the first target mentioned). If
any of the object files it depends on are older than their corresponding
source file, then these object files are recreated.
The targets needn't be programs. In this example, typing `{\tt make clean}'
will remove any files created during the compilation process.
\begin{verbatim}
# Makefile for dtree
DEFS = -Aa -DSYSV
CFLAGS = $(DEFS) -O
LDFLAGS =
LIBS = -lmalloc -lXm -lXt -lX11 -lm
BINDIR = /usr/local/bin/X11
MANDIR = /usr/local/man/man1
OBJECTS_A = dtree.o Arc.o Graph.o #using XmGraph
ARCH_FILES = dtree.1 dtree.c Makefile Dtree Tree.h TreeP.h \
dtree-i.h Tree.c Arc.c Arc.h ArcP.h Graph.c Graph.h GraphP.h
dtree: $(OBJECTS_A)
$(CC) -o dtree $(LDFLAGS) $(OBJECTS_A) $(LIBS)
Arc.o: Arc.c
$(CC) -c $(CFLAGS) Arc.c
Graph.o: Graph.c
$(CC) -c $(CFLAGS) Graph.c
dtree.o: dtree.c
$(CC) -o dtree.o -c $(CFLAGS) -DTREE dtree.c
install: dtree dtree.1
cp dtree $(BINDIR)
cp dtree.1 $(MANDIR)
clean:
rm -f dtree *.o core tags a.out
\end{verbatim}
\section{Debugging}
\subsection{Utilities}
\begin{description}
\item[lint :- ] \label{LINT} is a program which gives the sort of warning
messages about `unused variables' and
`wrong number of arguments' that non-C compilers usually give. {\tt lint}
takes most of the same arguments as the compiler. It needs special
libraries which are already provided.
\item[cflow :- ]
To show which functions call which, use {\tt cflow}. This produces an
indented output which also gives an idea of function call nesting.
\item[warnings :- ] Some compilers have flags to turn on extra
checking. {\tt gcc} for example has a {\tt -Wall} option which gives a
list of suspicious constructions as well as the usual compile errors.
\item[cb :- ]
To standardise the indentation of your program, send it through {\tt cb},
a C beautifier;
\begin{verbatim}
cb ugly.c > lovely.c
\end{verbatim}
\item[cxrefs :- ] tells you where variables and functions are mentioned.
It's especially useful with multi-file sources.
\item[adb :- ]
I only use {\tt adb} to see why a core dump happened. If `{\tt myprog}' causes
a core dump then
\begin{verbatim}
adb myprog
$c
\end{verbatim}
will show you what function's return addresses were on the stack when
the crash happened, and what hex arguments they were called with. Quit
using \verb|$q|
\item[Symbolic Debuggers :- ]
{\tt dbx}, {\tt xdb}, or {\tt gdbx} may be available to you. They are
symbolic source-level debuggers under which you can run a
program in trace mode allowing you to use breakpoints, query values,
etc. To use this you will have to first compile your program with
the {\tt -g} flag.
\item[perror() :- ] When a system call fails it generally sets an
external variable called {\tt errno} to indicate the reason for
failure. Using {\tt perror()} (which takes a string as an argument)
will print the string out and print the error message corresponding
to the value of {\tt errno}
\item[assert() :- ]
This is useful for putting diagnostics into programs.
When it is executed, if the expression it takes as an
argument is false (zero), {\tt assert} prints the
expression's value and the location of the assert call.
See the on-line manual page for more details.
\item[cdecl :- ] This program \label{CDECL} can help
with C declarations. See man page for details. Some examples:-
\begin{small}
\begin{verbatim}
tw012/tpl: cdecl declare fptab as array of pointer to function returning int
int *fptab[]()
tw012/tpl: cdecl explain int '*fptab[]()'
declare fptab as array of pointer to function returning int
\end{verbatim}
\end{small}
{\tt cdecl} is available from archives in {\tt comp.sources.unix/volume6}.
\end{description}
\subsection{Some Common mistakes}
C is based on the principle that programmers know what they're
doing, so it lets them get on with it and doesn't get in their way.
Throughout this document common errors have a Warning sign in the
margin. A checklist of more errors is given here.
\subsubsection{Miscellaneous}
\begin{itemize}
\item
A common mistake is to type `{\tt =}' instead of `{\tt ==}'.
\begin{verbatim}
if (i=3)
return 1;
else
return 0;
\end{verbatim}
will always return {\tt 1} because the assignment `{\tt i=3}' has the
value {\tt 3} and {\tt 3} is true!
\item
Comments in C can't be nested. Use the preprocessor directives to
temporarily `comment out' blocks of code. Suppose you had the following
code.
\begin{verbatim}
if (i=6)
z=mean(x,y); /* get the xy mean */
mean(z,y);
\end{verbatim}
If you decided not to risk running {\tt mean} you might do
\begin{verbatim}
/* comment this fragment out
if (i=6)
z=mean(x,y); /* get the xy mean */
mean(z,y);
*/
\end{verbatim}
but it wouldn't work because the first `{\tt /*}' would be matched
by the `{\tt */}' on the `{\tt mean(x,y)}' line (the `{\tt /*}' on that
line being
ignored), and `{\tt mean(z,y);}' wouldn't be commented out at all.
In this case the final `{\tt */}' would be flagged as an error,
but you won't always be so lucky.
\item
\begin{verbatim}
...
i = 3;
j = 10;
while (i<100);
i = i+j;
...
\end{verbatim}
This {\tt while} loop will go on for ever. The semicolon after the
while condition is a null statement which forms the body of the loop so
{\tt i} will always be {\tt 3}.
Take away that semicolon and \verb|i = i+j| becomes the body, which is
probably what was intended.
\item
When you have an if-else statement nested in another if statement,
always put braces around the if-else. Thus, never write like this:
\begin{verbatim}
if (foo)
if (bar)
win ();
else
lose ();
\end{verbatim}
(the {\tt else} matches the closest {\tt if}), always like this:
\begin{verbatim}
if (foo)
{
if (bar)
win ();
else
lose ();
}
\end{verbatim}
\item
Don't be fooled by indentation. In the following fragment only the
execution of the `{\tt j = 7;}' statement is conditional upon the
value of {\tt i}.
\begin{verbatim}
...
if (i==7)
j = 7;
k = 7;
...
\end{verbatim}
\item
The order of operations in an expression isn't guaranteed to be
left-to-right. A line like
\begin{verbatim}
a[i++] = b[i++];
\end{verbatim}
will have different results according to whether or not the
{\tt i} on the left-hand side is calculated before the right-hand side
is evaluated.
\item
The order of operator precedence sometimes surprises people.
\begin{verbatim}
...
FILE *fp;
...
if (fp=fopen(filename, "r") == NULL)
return (NULL);
\end{verbatim}
Here the intention is to try opening a file, then compare the resulting
{\tt fp} to {\tt NULL} to see if {\tt fopen} failed. Unfortunately,
what actually happens first is the test {\tt (fopen(filename, "r") == NULL)}
which has an integer result (non-zero if the statement is true). This
result is then assigned to {\tt fp}. The compiler should warn you about
this problem. The code should have some extra brackets:-
\begin{verbatim}
...
FILE *fp;
...
if ((fp=fopen(filename, "r")) == NULL)
return (NULL);
\end{verbatim}
\item
The following won't work as expected because the `\verb|~|' character
needs to be interpreted by the shell.
\begin{verbatim}
if ((fp=fopen("~/data", "r")) == NULL)
return (NULL);
\end{verbatim}
You'll have to find out your home directory (use {\tt getenv("HOME")})
and append to it.
\item
{\tt scanf} takes {\em pointers} to the variables that are going to be set.
The following fragment will cause a crash
\begin{verbatim}
...
int i;
scanf("%d",i); /* this should be scanf("%d",&i) */
\end{verbatim}
\item
The most uncomfortable bugs are those that seem to move as you hunt
them down. Put in some {\tt printf()} statements and they just
disappear -- or seem to. This probably means that you're writing off
the end of an array or that one of your pointers has gone astray.
You can avoid the use of naked fixed arrays by wrapping them in a structure
with pre and post sentinels, e.g.
\begin{verbatim}
struct fooby {
int prefix;
char myarray[N];
int postfix;
};
\end{verbatim}
and adding code to initialize the sentinels and check whether they have been
tampered with. More simply, you could do something like
\begin{verbatim}
#define BUFLEN 10
int x[BUFLEN], y;
...
if (y >= BUFLEN || y<0)
[error code here]
else
x[y] = 255;
...
\end{verbatim}
\item
There's a big difference between \verb|'\0'| and \verb|"\0"|. Suppose
you had
\begin{verbatim}
char str[100];
char *str_ptr;
str_ptr = str;
\end{verbatim}
then {\tt str\_ptr} and {\tt str} would both point to the first element in
the array. Suppose you wanted to initialise this string by making the first
element a zero byte. You could do
\begin{verbatim}
strcpy(str_ptr, "\0") /* or strcpy(str_ptr, "") */
\end{verbatim}
or
\begin{verbatim}
*str_ptr = '\0';
\end{verbatim}
but
\begin{verbatim}
str_ptr = "\0";
\end{verbatim}
would do something quite different. It would create a string in your
executable (namely \verb|"\0"|) and set {\tt str\_ptr} to point to it
with potentially disastrous effects.
\item
Turning on optimisation may change the behaviour of your program,
especially if the program isn't perfect.
For instance, if optimisation re-positions a variable into a
register it's less likely to be {\tt 0} initially, so if you've
not initialised variables before use you might get a surprize.
\end{itemize}
\subsubsection{declaration mismatch}
\begin{itemize}
\item
{\tt getchar} returns an integer, not a {\tt char} as you might expect.
If the integer value returned is
stored into a character variable and then compared against
the integer constant {\tt EOF}, the comparison may never succeed,
because sign-extension of a character on widening to integer
is machine-dependent.
{\em Read the manual page} before using a function.
\item
Suppose a function {\tt reverse} takes a string. If the \KandR\ programmer
accidentally writes
\begin{verbatim}
reverse (str)
{
char *str;
...
}
\end{verbatim}
rather than
\begin{verbatim}
reverse (str)
char *str;
{
...
}
\end{verbatim}
the compiler might not warn the programmer that the formal parameter {\tt str}
has the default type {\tt int} and a local variable {\tt str} is created
which isn't initialised.
\item
In the next example, it looks as if the programmer meant to define 2
pointers to integers. In fact, {\tt ptr2} is being defined as an integer.
\begin{verbatim}
int* ptr1, ptr2;
\end{verbatim}
\item
In \KandR\ the following code would crash; (\ANSI\ does automatic type
conversion)
\begin{verbatim}
int mean(num1, num2)
int num1, num2;
{
...
}
int i, answer;
float f;
/* deliberate mistake! */
answer = mean(f,j);
printf("The mean of %f and %d is %d\n", f, j, answer);
\end{verbatim}
C functions usually get given arguments via the stack.
Calling functions put values on the stack then peel the same number of bytes
off when returned to, so it doesn't matter to \KandR\ if the subfunction
doesn't use
or declare all the arguments that it is given. It doesn't even matter if
it declares more arguments than given by the caling function as long
as it doesn't write to these values. Were it to do so, it might well
overwrite the address that the called function should return to. Such a
problem might not be recognised for quite a while, and isn't easy to
track down. This is where `{\tt lint}' (see \ref{LINT}) becomes useful
\item
If in one source file you have \verb|int array[100]| and you want to use this
array from another source file, you mustn't declare as
\verb|extern int *array| but as \verb|extern int array[]|. The clearest
explanation of why this is so comes from Chris Volpe ({\tt [email protected]})
When you declare \verb|int array[100];| the compiler sets aside storage for
100 ints, at say, address 500. The compiler knows that {\tt array} is an
array, and
when it tries to generate code for an expression like \verb|array[3]|, it
does the following: It takes the starting address of the array (500), and
adds to that an offset equal to the index (3) times the size of an int
(typically 4) to get an address of \verb|500+3*4=512|. It looks at the int
stored at address 512 and there's the int.
When you give an external declaration in another file like
\verb|extern int *array;|,
the compiler takes your word for it that \verb|array| is a pointer. The linker
resolves the symbol for you as an object that resides at address 500. But
since you lied to the compiler, the compiler thinks there's a pointer variable
stored at address 500. So now, when the compiler sees an expression like
\verb|array[3]|, it generates code for it like this: It takes the address of
the
pointer (500) and, assuming there's a pointer there, reads the value of the
pointer stored there. The pointer will typpically reside at address 500
through 503. What's actually in there is indeterminate. There could be a
garbage value stored there, say 1687. The compiler gets this value, 1687, as
the address of the first int to which the pointer points. It then adds the
scaled index offset (12) to this value, to get 1699, and tries to read the
integer stored at address 1699, which will likely result in a bus error or
segmentation violation.
The thing to remember about all this is that even though
\verb|array[index]| and \verb|pointer[index]| can be used interchangeably in
your source code, the compiler generates very different object code depending
on whether you are indexing off an array identifier or a pointer identifier.
\end{itemize}
\subsubsection{malloc}
{\tt malloc()} allocates memory dynamically.
The standard {\tt malloc()} and {\tt free()} functions need to be efficient
and can't
check the integrity of the heap on every call. Therefore, if the heap gets
corrupted, seemingly random behaviour can occur. The
following code won't work.
\begin{verbatim}
char *answer;
printf("Type something:\n");
gets(answer);
printf("You typed \"%s\"\n", answer);
\end{verbatim}
The pointer variable {\tt answer}, which is handed to the {\tt gets} function
as the location into which the response should be stored, has not
been set to point to any valid storage. That is, we cannot say
where the pointer {\tt answer} points. Since local variables are not
initialized, and typically contain garbage, it is not even
guaranteed that {\tt answer} starts out as a null pointer.
The simplest way to correct the question-asking program is to use a
local array, instead of a pointer, and let the compiler worry about
allocation:
\begin{verbatim}
#include
char answer[100], *p;
main(){
printf("Type something:\n");
fgets(answer, 100, stdin);
if((p = strchr(answer, '\n')) != NULL)
*p = '\0';
printf("You typed \"%s\"\n", answer);
}
\end{verbatim}
Note that this example also uses {\tt fgets} instead of {\tt gets}
(always a
good idea), so that the size of the array can be specified and
{\tt fgets} will not overwrite the end of the array if the user types an
overly-long line, though unfortunately for this example, {\tt fgets}
does not
automatically delete the trailing \verb|\n|, as {\tt gets} would.
Type \verb|man dbmalloc| to find out about
a malloc library that does extensive error checking.
Alignment problems can arise if {\tt malloc} is used carelessly. Processors
have different rules about (for instance) whether a {\tt long} can be stored
starting at an odd memory location. If you try to break these rules, your
program will crash giving little or no clue why. The {\tt HP RISC} chips
only permit a {\tt double} to start at an address divisible by 8, so trying
something like
\begin{verbatim}
char *block = (char*) malloc(sizeof(double));
double d = 1.2;
* (double*)block = d;
\end{verbatim}
is likely to crash.
\subsubsection{Find the bug}
What looks wrong with these programs?
\begin{itemize}
\item
\begin{verbatim}
#include
#include
main()
{
int i;
for (i=0; i<10; i=i+1);
printf("i is %d\n",i);
}
\end{verbatim}
\item
\begin{verbatim}
#include
#include
main()
{
int i;
for (i=0; i<10; i=i+1)
if (i=2)
printf("i is 2\n");
else
printf("i is not 2\n");
}
\end{verbatim}
\item
\begin{verbatim}
#include
#include
main()
{
int i;
for (i=0; i<10; i=i+1)
if (i<2)
printf("i is less than, but\n");
printf("but not equal to, 2\n");
}
\end{verbatim}
\item
\begin{verbatim}
#include
#include
main()
{
int i;
i = 0;
while (i < 10);
i = i + 1;
}
\end{verbatim}
\item
\begin{verbatim}
#include
#include
main()
{
int i;
for (i=0; i<10; i=i+1)
switch(i){
case 0: printf("i is 0\n");
case 1: printf("i is 1\n");
default: printf("i is more than 1\n");
}
}
\end{verbatim}
\item
the following code works on some machines but crashes on others ...
\begin{verbatim}
#include
#include
typedef struct {
double *par;
double *pos;
double *vel;
} ajoint;
main()
{
ajoint *joint;
joint = (ajoint *) malloc(sizeof(ajoint) + sizeof(double));
joint->pos = (double*) (joint +1);
*(joint->pos) = 0;
}
\end{verbatim}
\end{itemize}
love-tex/slides.tex 100644 0 0 27127 5600705274 12743 0 ustar root root \documentstyle[a4_local]{article}
\pagestyle{empty}
\begin{document}
\large
\section*{Language Philosophy}
\begin{itemize}
\item Semi-portable high-level assembler
\item Not a conventional high-level language
\item Better as target language of compiler
\end{itemize} \hspace{.3cm} \begin{itemize}
\item Almost no restrictions
\item A debugging C compiler is forever impossible
\end{itemize} \hspace{.3cm} \begin{itemize}
\item Foul to optimise
\item Assumed that the programmer does this
\item Often slow on RISC machines
\end{itemize} \hspace{.3cm} \begin{itemize}
\item Assumes the UNIX linker
\item Causes trouble on most other systems
\end{itemize} \hspace{.3cm} \begin{itemize}
\item Very compact to write
\item Enter the Obfuscated C Contest!
\end{itemize} \hspace{.3cm} \begin{itemize}
\item Defined by the compiler source
\item No usable language specification before ANSI
\end{itemize}
\newpage
\section*{Program Structure}
\begin{itemize}
\item Built up of files that include files
\item Traditionally sources and headers
\item Libraries are just compiled source
\item 1960s model of linking
\end{itemize} \hspace{.3cm} \begin{itemize}
\item A file is declarations and definitions
\item Normally top-level <-> external
\item No function nesting
\end{itemize} \hspace{.3cm} \begin{itemize}
\item In ANSI can initialise all data
\item Stack variables can have any valid value
\end{itemize} \hspace{.3cm} \begin{itemize}
\item Function definitions are header + block of code
\item Block is declarations + statements
\item A block is also a statement
\item Block scope is default
\end{itemize} \hspace{.3cm} \begin{itemize}
\item Syntax is not context-free (Algol68 is)
\item No useful recovery points (unlike Fortran)
\item Many common errors lead to collapse of parsing
\item Often have to fix just first error
\end{itemize}
\newpage
\section*{Name Spaces}
\begin{itemize}
\item Macro names are completely distinct
\item Library relies on punning with functions
\item Some tricks are needed here
\end{itemize} \hspace{.3cm} \begin{itemize}
\item Member names of struct and union are per type
\item Labels are separate
\item Tags of structs, unions and enums are separate
\item All other identifiers
\end{itemize} \hspace{.3cm} \begin{itemize}
\item Names are case-sensitive and 31 characters
\item External names may be monocase and 6 characters
\item Compiler does not have to diagnose errors
\end{itemize} \hspace{.3cm} \begin{itemize}
\item Reserved names begin with \verb|__| or \verb|_A| to \verb|_Z|.
\item External names beginning \verb|_| are reserved
\item Name visibility is messy and ill-defined
\end{itemize}
\newpage
\section*{Declarations}
\begin{itemize}
\item Write expression to get back to base type
\item Brackets bind modifiers outside them!
\end{itemize} \hspace{.3cm} \begin{itemize}
\item Algol 68 type inverted w.r.t. the identifier
\item Function prototypes are an exception
\item ANSI checks mistakes here (unlike \verb|K&R|)
\item Constructions like {\tt double(*)[]}
\end{itemize} \hspace{.3cm}
Modifiers are fairly obvious, if unclean. Simple uses are no problem.
Only register affects representation. Modifiers are of three types:
\begin{itemize}
\item Some control where object is stored
\item Some control arithmetic rules
\item Plus const and volatile
\end{itemize} \hspace{.3cm} \begin{itemize}
\item Compound types are conventional
\item Security is textual, and only at compilation
\item Execution equivalencing is whatever works
\item Mixture of allowed, forbidden and both!
\end{itemize}
\newpage
\section*{Function Declarations etc.}
\begin{itemize}
\item \verb|K&R| is like Fortran - only result type
\item ANSI closer to Algol 68 - allows prototypes
\item There is a clean way to allow for both
\end{itemize} \hspace{.3cm}
Variable numbers of arguments are handled completely differently
in ANSI and \verb|K&R|
\begin{itemize}
\item Writing dual definitions is almost impossible
\item \verb|K&R| is implicit, using macros
\item ANSI is explicit, also using macros
\end{itemize} \hspace{.3cm} \begin{itemize}
\item \verb|K&R| promotions are to at least int or double
\item Ditto for ANSI variable arguments
\item char, short or float arguments are inadvisable
\item Result types are no problem
\end{itemize} \hspace{.3cm} \begin{itemize}
\item Function values are addresses
\item Incompatible with data pointers (no sizeof etc.)
\item Punning is usually possible, and assumed
\end{itemize}
\newpage
\section*{Pointers}
Three basic types of pointer:
\begin{itemize}
\item Function addresses
\item Data pointers
\item NULL (or integer 0, cast)
\end{itemize} \hspace{.3cm} \begin{itemize}
\item All function address types semi-equivalent
\item When used, must be in correct type
\item Compatible only with NULL (or 0)
\item Pointers to function addresses are data pointers
\end{itemize} \hspace{.3cm} \begin{itemize}
\item All data pointers are start of storage
\item Can be cast to char * or void * and back
\item All data can be treated as array of char
\end{itemize} \hspace{.3cm} \begin{itemize}
\item Main difference is `alignment'
\item Legal casting does conversion correctly
\item Type modifiers are probably irrelevant
\end{itemize} \hspace{.3cm} \begin{itemize}
\item Pointer arithmetic is as expected
\item Units are data objects pointed to
\item Implicit use of sizeof
\item Constant pointer expressions may be allowed
\end{itemize} \hspace{.3cm} \begin{itemize}
\item ANSI pointer subtraction is very limited
\item Only for pointers to sub-objects of same object
\item Stack (or stack frame) not an object
\end{itemize}
\newpage
\section*{Arrays}
\begin{itemize}
\item Arrays are both Pascal-like and BCPL-like
\item Pascal-like only during compilation
\item BCPL-like during compilation and execution
\item Problem only with several dimensions
\end{itemize} \hspace{.3cm} \begin{itemize}
\item {\tt double a[5][3]} is 5-item array of 3-item arrays,
not a multi-dimensional array.
\item Reasons for confusion are very technical
\end{itemize} \hspace{.3cm} \begin{itemize}
\item Arrays and pointers are mutually convertible
\item Implies {\tt a[][]} is rather like {\tt a**}
\item This does not recurse, because of two natures
\end{itemize} \hspace{.3cm} \begin{itemize}
\item \verb| double[][] <-> double(*)[] double**|
\item Pointer arithmetic is very different (sizeof)
\item {\tt ++(double**)...} adds 4 bytes
\item {\tt ++(double(*)[3])...} adds 24 bytes
\item {\tt ++(double(*)[])...} is an error
\end{itemize} \hspace{.3cm} \begin{itemize}
\item All array values are address of first element
\item This does apply recursively
\item After {\tt double a[5][3], (void*)a == (void*)a[0][0]}
\item Applies during compilation and execution
\end{itemize}
\newpage
\section*{Expressions}
Right-minded programmers will have no trouble. However, expect
optimisation bugs. These cause major problems with many UNIX programs.
Sometimes optimisation has to be switched off.
\begin{itemize}
\item Unlike any rational or clean language (\verb|a&&b|, \verb|a+++++b| etc).
\item Old \verb|K&R| \verb|=+| etc. are now dead
\item ANSI (but not \verb|K&R|) defines syntax
\item Prefix, postfix, infix and multifix operators
\item Must bracket for clarity
\end{itemize} \hspace{.3cm} \begin{itemize}
\item ANSI defines `sequence points' to serialise
\item Assignment, reading volatile, most functions
\item Relies on order of evaluation of tree structure
\end{itemize} \hspace{.3cm} \begin{itemize}
\item Fortran-like automatic type conversion is OK
\item Signed/unsigned conversions are a major trap
\item Two common rules, and ANSI requires one
\item Usually a switch to use the other
\item Always use explicit casts is anything negative
\end{itemize} \hspace{.3cm} \begin{itemize}
\item Characters are a form of integer
\item Little problem to BCPL programmers
\item Warning: 'A' is of type int, not char
\end{itemize}
\newpage
\section*{sizeof}
\begin{itemize}
\item sizeof is evaluated during compilation only
\item Takes bracketed type name or ignored expression
\item Some illegal expressions are allowed
\item Syntactic problems; e.g. sizeof (int) + a
\item Mistakes cause most obscure effects
\end{itemize} \hspace{.3cm} \begin{itemize}
\item Implicit use in copying, pointer arithmetic etc.
\item Hence all sizes fixed at compilation time which is why
variable arrays ({\tt char buff[i]} cannot be added.
\end{itemize}
\newpage
\section*{Casts}
Three kinds of cast:
\begin{itemize}
\item void casts (as in Algol 68) - no problem
\item arithmetic casts
\item pointer casts
\end{itemize} \hspace{.3cm} \begin{itemize}
\item Some (not all) operators imply implicit casts
\item Not just when operands different values
\item Trap when using signed/unsigned values
\item Other circumstances may imply casts as well
\end{itemize} \hspace{.3cm} \begin{itemize}
\item Arithmetic casts \verb|<->| type conversion functions
\item Fairly simple, but may not behave as expected
\item Explicit casting is an ordinary operator
\item Implicit casts applied too
\end{itemize} \hspace{.3cm} \begin{itemize}
\item Function addresses can be cast to one another
\item Always reversible, but must be used correctly
\end{itemize} \hspace{.3cm} \begin{itemize}
\item Data casting must go through weaker `alignment'
\item Always safe to {\tt void *} or {\tt char *} and back
\item Algol 68 programmers should watch out here
\end{itemize} \hspace{.3cm} \begin{itemize}
\item Function, data pointers and integers distinct
\item Exception is {\tt NULL} (or integer 0)
\item Mixing them is common practice, allowed by almost all compilers,
incompatibly
\end{itemize} \hspace{.3cm} \begin{itemize}
\item Can treat any data as array of char
\item Library relies heavily upon this
\item Casting to {\tt char *} and using it is normal
\end{itemize}
\newpage
\section*{Arithmetic}
\begin{itemize}
\item Slight assumption of 2's complement; variant systems may be very slow
\item Unsigned integers may not overflow
\item Signed arithmetic is conventional
\item Conversion is defined one way only
\item All integer conversions are a trap
\end{itemize} \hspace{.3cm} \begin{itemize}
\item Floating-point assumes no underflow or inexact
\item
\item Theoretically not even constant during a run
\end{itemize} \hspace{.3cm} \begin{itemize}
\item Defined limits are OK, and all exist
\item int is commonly 16 or 32.
\item Must use conditional compilation to cope with machine-dependencies
\end{itemize} \hspace{.3cm} \begin{itemize}
\item Brackets are NOT honoured in \verb|K&R|
\item Must split into separate statements
\item ANSI honours all brackets
\item Can affect overflow, rounding etc.
\end{itemize}
\newpage
\section*{Statements}
\begin{itemize}
\item Same as BCPL, but less clean
\item Expression statement replaces assignment
\item Only a problem if unreasonably complex code
\end{itemize} \hspace{.3cm} \begin{itemize}
\item `for' statement is merely syntactic sugar for `while'
\item No constraints encourages obscure uses
\item Can disable optimisation - ghastly on RISC
\item Use a Fortran- or Pascal-like style
\end{itemize} \hspace{.3cm} \begin{itemize}
\item Returning no value is always allowed (if unused)
\item Reaching end of function is equivalent
\item Causes compilers to abandon diagnosing errors
\end{itemize}
\newpage
\section*{Invoking C Programs}
\begin{itemize}
\item ANSI defines under language
\item main called with arg. count and array of strings
\item Strings are updateable, tokenised arguments
\item Alternatively may be declared with no arguments
\item First argument is program name, and ends with NULL
\end{itemize} \hspace{.3cm} \begin{itemize}
\item `Return from main' and `exit with a return code' are defined to be
equivalent. A plain return from main sets an undefined code
\end{itemize}
\end{document}
love-tex/teaching_C.bib 100644 0 0 4566 5600705275 13423 0 ustar root root @BOOK
{KandR,
AUTHOR = "Kernighan, Brian W. and Ritchie, Dennis M.",
TITLE = "{The C Programming Language Second Edition}",
PUBLISHER = "Prentice-Hall, Inc.",
YEAR = 1988
}
@BOOK
{Hol87,
AUTHOR = "Hollub,Allen I.",
TITLE = "{The C Companion}",
PUBLISHER = "Prentice Hall",
YEAR = 1987
}
@BOOK
{HandS,
AUTHOR = "Harbison,Samuel P. and Steele, Guy L.",
TITLE = "{C: A Reference Manual}",
PUBLISHER = "Prentice Hall",
YEAR = 1987
}
@BOOK
{CTandP,
AUTHOR = "Andrew Koenig",
TITLE = "{C Traps and Pitfalls}",
PUBLISHER = "Addison-Wesley",
YEAR = 1989
}
@BOOK
{KP78,
AUTHOR = "Kernighan, Brian W. and Plauger, P.J.",
TITLE = "{The Elements of Programming Style}",
PUBLISHER = "McGraw-Hill",
YEAR = 1978
}
@BOOK
{H90,
AUTHOR = "Mark Horton",
TITLE = "{Portable C Software}",
PUBLISHER = "Prentice-Hall",
YEAR = 1990
}
@TECHREPORT
{ansi,
AUTHOR = "{X3J11}",
TITLE = "{Draft Proposed American National Standard for Information
Systems} --- {Programming Language C}",
INSTITUTION = "{ANSI Accredited Standards Committee,
X3 Information Processing Systems}",
MONTH = "December", YEAR = 1988,
NUMBER = "{X3J11/88--158}"
}
@TECHREPORT
{style,
AUTHOR = "Cannon, L.W.",
TITLE = "{Recommended C Style and Coding Standards}",
MONTH = "November", YEAR = 1989
}
@BOOK
{NRC,
AUTHOR = "William H. Press and Brian P. Flannery and
Saul A. Teukolsky and William T. Vetterling",
TITLE = "{NUMERICAL RECIPES in C: The Art of Scientific Computing}",
PUBLISHER = "Cambridge University Press",
YEAR = 1988
}
@BOOK
{BBD,
AUTHOR = "Banahan and Brady and Doran",
TITLE = "{The C Book}",
PUBLISHER = "Addison Wesley",
YEAR = 1988
}
@MANUAL
{HP,
TITLE = "{HP-UX Portability Guide}",
ORGANIZATION = "Hewlett-Packard Company",
YEAR = 1988
}
@BOOK
{KP,
AUTHOR = "Kernighan,B.W. and Pike,R",
TITLE = "{The UNIX Programming Environment}",
PUBLISHER = "Prentice-Hall",
YEAR = 1984
}
@BOOK
{Qualline,
AUTHOR = "Steve Oualline",
TITLE = "{Practical C Programming}",
PUBLISHER = "O'Reilly \& Associates, Inc",
YEAR = ???
}
@BOOK
{Korsh,
AUTHOR = "Korsh,J.F.. and Garrett,L.J.",
TITLE = "{Data Structures, Algorithms, and Program Style using C}",
PUBLISHER = "PSW-Kent",
YEAR = 1988
}
love-tex/teaching_C.tex 100644 0 0 45025 5600705276 13503 0 ustar root root % Copyright (c) 1993 by T.P.Love. This document may be copied freely
% for the purposes of education and non-commercial research.
% Cambridge University Engineering Department,
% Cambridge CB2 1PZ, England.
\documentstyle[a4,fancyheadings,bitmap]{article}
\def\KandR{{\em K\&R C}}
\def\Eg{{\em E.g.}}
\def\ANSI{{\tt ANSI C}}
\def\Warning{\Bitmap{warning.px}{1pt}}
%\def\Warning{**}
\newenvironment{miniverb}{\begin{verbatim} }
{\end{verbatim} }
\newlength{\minitw}
\setlength{\minitw}{2.25in}
\pagestyle{fancy}
\begin{document}
\bibliographystyle{plain}
\nocite{Hol87}
\nocite{HandS}
\nocite{CTandP}
\nocite{KP78}
\nocite{H90}
\nocite{NRC}
\nocite{BBD}
\nocite{Qualline}
\nocite{Korsh}
\title{ANSI C for Programmers\\
on UNIX Systems}
\author{Tim Love\\
Cambridge University engineering Department\\
{\tt [email protected]}}
\maketitle
\noindent This document aims to:-
\begin{itemize}
\item Introduce C by providing and explaining examples of common
programming tasks.
\item Enable the reader to learn from available source code by
clarifying common causes of incomprehension.
\end{itemize}
\noindent Coverage is not meant to be uniform: pedantry will be selective,
aimed at describing aspects of C which are not present in other languages
or are different to what a programmer from another language might expect.
For a full description of C refer to one of the many books in the
bibliography.
The first part of the document is an informal introduction to C. After
the 1st set of exercises a more comprehensive description is given. After
the 2nd set of exercises selected topics are covered.
The exercises and examples form an integral
part of the course, containing information not duplicated elsewhere.
Carole Klein and Nick McLaren (Cambridge Computer Lab),
Andy Piper, Campbell Middleton and James Matheson (CUED), and the
contributors to {\tt comp.lang.c} have all helped with this document.
All suggestions and corrections should go to Tim Love, CUED
({\tt [email protected]}).
\begin{table}[b]
Copyright \copyright 1993 by T.P.Love.
This document may be copied freely for the purposes
of education and non-commercial research.
Cambridge University Engineering Department,
Cambridge CB2 1PZ, England.
\end{table}
\newpage
\tableofcontents
\vspace{.5cm}
\noindent
{\Large \bf List of Demo Programs}
\begin{tabular}{lll}
{\bf Program} & {\bf Page} & {\bf Description} \\
{\tt basics.c} & \pageref{DEMO1} & basics\\
{\tt strings.c} & \pageref{DEMO2} & strings\\
{\tt array.c} &\pageref{ARRAY_DEMO} & 2D arrays\\
{\tt mallocing.c} & \pageref{DEMO3} & malloc\\
{\tt files.c} & \pageref{DEMO4} & file i/o\\
{\tt line\_nums.c} & \pageref{LINE_NUMS} & filter\\
\end{tabular}
\listoffigures
The newest version of this document (Postscript and \LaTeX ) is available
\begin{itemize}
\item By {\tt gopher}
\begin{verbatim}
gopher.eng.cam.ac.uk:CUED Published/Computer Service/teaching_C.ps
\end{verbatim}
and
\begin{verbatim}
gopher.eng.cam.ac.uk:CUED Published/Computer Service/LaTeX/
\end{verbatim}
\item By {\tt ftp}
\begin{verbatim}
unix> ftp svr-ftp.eng.cam.ac.uk
Name: anonymous
Password: (send userid)
ftp> cd misc
ftp> binary
ftp> get love_C.ps.Z
ftp> get love_C.shar
ftp> quit
\end{verbatim}
\end{itemize}
\newpage
\input{part1}
\section{Exercises 1}
\begin{enumerate}
\item Write a routine called {\tt base} that does the following
\begin{verbatim}
void base( int number, int base){
/* print `number' to the given `base' */
...
}
\end{verbatim}
Then write a {\tt main} routine to test it.
\item {\tt pascal} has a function called {\tt odd}, that given an
integer returns 1 if the number is odd, 0
otherwise. Write an {\tt odd} function for C and write a {\tt main}
routine to test it. (hint -- You can use the fact that in C, if {\tt i}
is an integer then {\tt (i/2)*2} equals {\tt i} only if {\tt i} is even).
\item Print a table of all the primes less than 1000. Use any method you want.
The sieve method is described here:-
aim to create an array `{\tt number}' such that if {\tt numbers[i] == PRIME}
then {\tt i} is a prime number.
First mark them all as being prime. Then repeatedly
pick the smallest prime you haven't dealt with and mark all its multiples
as being non prime. Print out the primes at the end. Here's a skeleton:-
\begin{verbatim}
#include
#include
#define PRIME 1 /* Create aliases for 0 and 1 */
#define NONPRIME 0
int numbers[1000];
void mark_multiples(int num){
/* TODO: Set all elements which represent multiples of num to NONPRIME. */
}
int get_next_prime(int num){
/* find the next prime number after `num' */
int answer;
answer = num+1;
while (numbers[answer] == NONPRIME){
answer= answer +1;
if (answer == 1000)
break;
}
return answer;
}
main(){
int i;
int next_prime;
/* TODO: Set all the elements to PRIME. Remember, the 1st element is
numbers[0] and the last is numbers[999] */
/* TODO: 0 and 1 aren't prime, so set numbers[0] and numbers[1]
to NONPRIME */
next_prime = 2;
do{
mark_multiples(next_prime);
next_prime = get_next_prime(next_prime);
} while(next_prime < 1000);
/* TODO: Print out the indices of elements which are still set to PRIME */
exit(0);
}
\end{verbatim}
The `{\tt TODO}' lines describe what code you
need to add in.
You can speed up this program considerably by replacing {\tt 1000}
where appropriate by something smaller. See page \pageref{EXERCISES3}
for details.
\end{enumerate}
\input{part2}
\section{Exercises 2}
To answer these exercises you'll need to be able to get keyboard input
from the user. For the moment, use the following fragment to get a
string from the user. {\tt str} needs to point to the start of a character
array.
\begin{verbatim}
char * get_string(char str[])
{
printf("Input a string\n");
return gets(str);
}
\end{verbatim}
\begin{enumerate}
\item The following code fragment uses many of the contractions mentioned
earlier. It comes from {\tt ghostscript}. Re-write it to make it
more legible.
\begin{verbatim}
int ccase = (skew >= 0 ? copy_right :
((bptr += chunk_bytes), copy_left))
+ (int)function;
\end{verbatim}
\item Write a program that invites the user to type in a string and prints
the string out backwards (The answer to this is in section
\ref{EXERCISES3}).
\item Write your own version of {\tt strchr} (see the manual page for
a description).
\item Write a program which reads in a string like ``20C'' or ``15F'' and
outputs the temperature to the nearest degree using the other scale.
The easiest way to parse the input string is to use {\tt sscanf} to
scan the input string for a number and a character. It will return the
number of items successfully read in.
\begin{verbatim}
...
int degrees;
char scale;
int return_value;
...
return_value = sscanf(str,"%d%c",°rees, &scale);
...
\end{verbatim}
\item The following program will be developed later in the handout.
Suppose you have a situation where you need to process a stream of things
(they might be scanned character images, chess positions or as in
this example, strings),
some of which might be duplicates. The processing might be CPU-intensive, so
you'd rather use the previously calculated values than re-process duplicate
entries. What's needed is a {\em look-up table}.
Each entry in the look-up table needs to have a record of the original
string and the result of the processing. A structure of type {\tt Entry}
\begin{verbatim}
typedef struct {
char str[64];
int value;
} Entry;
\end{verbatim}
will do for now. For our purposes it doesn't matter much what the
processing routine is. Let's use the following, multiplying all the
characters' values together.
\begin{verbatim}
int process(char *str){
int val = 1;
while (*str){
val = val * (*str);
str++;
}
return val;
}
\end{verbatim}
To get strings into the program you can use the {\tt get\_string} function.
Now write a program that reads strings from the keyboard. If the string
is new, then it's processed, otherwise its value is looked up in a table.
The program should stop when `{\tt end}' is typed. Here's a skeleton
program to get you started.
\begin{verbatim}
/* hash1.c */
/* TODO include standard include files */
/* The following 2 lines use the preprocessor to create aliases.
Note that these lines DON'T end with a `;'
*/
#define TABLE_SIZE 50
#define MAX_STR_LEN 64
typedef struct {
char str[MAX_STR_LEN];
int value;
} Entry;
char str[MAX_STR_LEN];
/* TODO Create an array of TABLE_SIZE elements of type Entry */
int process(char *str){
int val = 1;
while (*str){
val = val * (*str);
str++;
}
return val;
}
char * get_string(char str[])
{
printf("Input a string\n");
return gets(str);
}
main(){
int num_of_entries = 0;
/* TODO Use get_string repeatedly. For each string:-
If the string says `end', then exit.
If the str is already in the table,
print the associated value
else
calculate the value, add a new
entry to the table, then print the value.
*/
}
\end{verbatim}
\item
The method used above can be improved upon. Firstly, it will
go wrong if there are too many strings.
By choosing an arbitrarily large value for {\tt TABLE\_SIZE} you could
overcome this problem, but the method of searching the table to see
whether an entry is new becomes very inefficient as the table grows.
A technique called {\em hashing} copes with this. First we need a
{\em hash function} which given a string produces a number in the
range {\tt 0..TABLE\_SIZE}. The following function just adds up the
value of the characters in the string and gets the remainder after
dividing by {\tt TABLE\_SIZE}.
\begin{verbatim}
int hashfn(char *str){
int total = 0;
int i;
while (i = *str++)
total += i;
return total % TABLE_SIZE;
}
\end{verbatim}
Now, whenever a string is to be processed, its hash value is calculated
and that is used as an index into the table. If that entry is
empty then the string is new and has to be processed. If the entry is
occupied, then the associated value can be accessed. This method is
flawed, but we'll deal with that problem later.
\begin{verbatim}
/* hash2.c */
/* TODO include standard include files */
#define TABLE_SIZE 50
#define MAX_STR_LEN 64
#define EMPTY -1
typedef struct {
char str[MAX_STR_LEN];
int value;
} Entry;
char str[MAX_STR_LEN];
/* TODO Create an array of TABLE_SIZE elements of type Entry */
int process(char *str){ /* Same as hash1.c */
int val = 1;
while (*str){
val = val * (*str);
str++;
}
return val;
}
char * get_string(char str[]) /* Same as hash1.c */
{
printf("Input a string\n");
return gets(str);
}
int hashfn(char *str){
int total = 0;
int i;
while (i = *str++)
total += i;
return total % TABLE_SIZE;
}
void set_table_values(void){
/* TODO set all the value entries in the table to EMPTY
(We'll assume that the process() routine doesn't
produce -1)
*/
}
int find_entry(char *str, int bucket){
/* TODO
if the entry is EMPTY then fill the entry in
and return the string's processed value,
else return the value of the entry.
*/
}
main(){
int bucket;
int val;
set_table_values();
/* TODO Use get_a_string repeatedly. For each string:-
use the hash function to find the string's entry
in the table, then do the following
*/
bucket = hashfn(str)
val = find_entry(str,bucket);
printf("Value of <%s> is %d\n",str, val);
}
\end{verbatim}
\item
The problem with this method is that the {\em hash function} may
produce the same value for different strings (for example, `{\tt act}'
and `{\tt cat}' will both map into the same entry). A simple way of
coping with such `{\em collisions}' is the following:-
If a table entry is occupied, check the string there to see if it's
the one being searched for. If it is, then return the associated value.
If it isn't the right string, then look
at subsequent entries until either
\begin{itemize}
\item an entry for the string is found
\item an empty entry is found.
\item It's been shown that all entries are full up.
\end{itemize}
You'll have to add just a few lines to the {\tt find\_entry} routine
of the previous exercise. Remember to cycle round when the bottom of
the table is reached.
A more robust
method (and the answer to the exercise here) is in the next set of
exercises (see section \ref{EXERCISES3}).
\end{enumerate}
\input{part3}
\section{Exercises 3}
\label{EXERCISES3}
\begin{enumerate}
\item Improve your {\tt primes} program so that
\begin{itemize}
\item It stops searching for primes in the range 0 to {\tt n}
once it has marked all the multiples of primes $\leq \sqrt{n}$
\item It can take as an argument a number to show the upper bound of
the primes to print out.
\end{itemize}
\item Put 10 numbers (either floats or integers) in a file, one per line.
Write a program that reads the numbers then prints their sum and
and average.
\item Read the 1st 10 uids from {\tt /etc/passwd}, save them in an array of
strings and sort them using {\tt qsort}.
\item
Take a simple program ({\tt demo3.c} will be ok) and break it up into
2 or 3 source files. See if you can compile them into an executable.
Try adding {\tt static} to variable and function definitions to see
what difference it makes. Write a makefile for it.
\item Write a program to count the number of ways that 8 queens can be placed
on a chess board without any 2 of them being on the same row, column or
diagonal.
\item Hashing - First a solution to the last hash exercise.
\begin{verbatim}
#include
#include
#define TABLE_SIZE 50
#define MAX_STR_LEN 64
#define EMPTY -1
typedef struct {
char str[MAX_STR_LEN];
int value;
} Entry;
char str[MAX_STR_LEN];
/* Create an array of elements of type Entry */
Entry table[TABLE_SIZE];
int process(char *str){
int val = 1;
while (*str){
val = val * (*str);
str++;
}
return val;
}
char * get_string(char str[])
{
printf("Input a string\n");
return gets(str);
}
int hashfn(char *str){
int total = 0;
int i;
while (i = *str++)
total += i;
return total % TABLE_SIZE;
}
void set_table_values(void){
/* set all the value entries in the table to EMPTY
(here we assume that the process() routine doesn't
produce -1)
*/
int i;
for (i =0;i
}
int find_entry(char *str, int bucket){
if (table[bucket].value == EMPTY){
strcpy(table[bucket].str,str);
table[bucket].value = process(str);
}
else{
if (strcmp(table[bucket].str,str)){
bucket = (bucket +1)% TABLE_SIZE;
return find_entry(str, bucket);
}
}
return table[bucket].value;
}
main(){
int bucket;
int val;
set_table_values();
/* Use get_string repeatedly. For each string:-
use the hash function to find the string's entry
in the table.
*/
while(get_string(str)){
if (! strcmp(str,"end")){
printf("Program ended\n");
exit(0);
}
bucket = hashfn(str);
val = find_entry(str,bucket);
printf("Value of <%s> is %d\n",str,val);
}
}
\end{verbatim}
Another approach to collisions is for
each entry in the hash table to be the beginning of a linked list of
items that produce the same hash function value. First we need to
alter the {\tt Entry} structure so that it includes pointer to
another {\tt Entry}. There's a slight complication here in that we
can't define a pointer to something which isn't defined yet, so we
introduce a {\em tag name} to the structure.
\begin{verbatim}
typedef struct _entry {
int value;
struct _entry *next;
char str[20];
} Entry;
\end{verbatim}
New entry structures can be generated using the following routine.
\begin{verbatim}
Entry *create_an_entry(void){
Entry *entry;
entry = (Entry*) malloc(sizeof (Entry));
return entry;
}
\end{verbatim}
{\tt find\_entry} needs to be re-written.
\begin{verbatim}
int find_entry(Entry ** entry, char *str){
if (*entry == NULL){
*entry = create_an_entry();
set_entry(*entry,str);
return (*entry)->value;
}
else{
if ((*entry) -> value != EMPTY){
if (!strcmp ((*entry) ->str, str)){
printf("Valueue for <%s> already calculated\n",str);
return (*entry) -> value;
}
else{
printf("There's a collision: <%s> and <%s> share\n",
(*entry) ->str, str);
printf("the same hashfn valueue\n");
find_entry(&((*entry)->next),str);
}
}
else{
printf("<%s> is a new string\n",str);
set_entry((*entry),str);
return (*entry)->value;
}
}
}
\end{verbatim}
The initial table can now be
\begin{verbatim}
/* Create an array of elements of type Entry */
Entry *table[TABLE_SIZE];
\end{verbatim}
These entries need to be initialised to {\tt NULL}.
Now write a program with the following {\tt main} routine to test all this out.
\begin{verbatim}
main(){
int bucket;
int value;
set_table_values();
/* Use get_string repeatedly. For each string:-
use the hash function to find the string's entry
in the table.
*/
while(get_string(str)){
if (! strcmp(str,"end")){
printf("Program ended\n");
exit(0);
}
bucket = hashfn(str);
value = find_entry(&(table[bucket]), str);
printf("Valueue of <%s> is %d\n",str,value);
}
}
\end{verbatim}
This program could be further elaborated
\begin{itemize}
\item At the moment, if a string is long enough it will be too big for
the array. Change the {\tt Entry} definition to:-
\begin{verbatim}
typedef _entry {
int val;
Entry *entry;
char *str;
}
\end{verbatim}
and change the code so that correctly sized space for each string is
created using {\tt malloc}.
\item A hash function should be quick to calculate and provide an even
spread of values to minimize collisions. Add some diagnostics to the
program and improve the hash function.
\end{itemize}
\end{enumerate}
\section{More information}
\begin{itemize}
\item The {\tt comp.lang.c} newsgroup has a great deal of information.
Read the {\tt Frequently Asked Questions} if nothing else.
\item Tutorials :- a set of tutorials written by Christopher Sawtell is
available from
\begin{itemize}
\item The {\tt gopher.eng.cam.ac.uk} gopher in {\tt CUED help/languages/C/Tutorials}.
\item {\tt paris7.jussieu.fr:/contributions/docs} by {\tt anon-ftp}.
\end{itemize}
\item Style Guides and Portability Guides appear on the net from time
to time. Read {\tt comp.lang.c} for details.
\end{itemize}
\appendix
\input{appendices}
\bibliography{teaching_C}
\end{document}
love-tex/teaching_C.toc 100644 0 0 6270 5600705276 13447 0 ustar root root \contentsline {section}{\numberline {1}Introduction}{4}
\contentsline {section}{\numberline {2}Compilation Stages}{5}
\contentsline {section}{\numberline {3}Variables and Literals}{6}
\contentsline {section}{\numberline {4}Aggregates}{6}
\contentsline {section}{\numberline {5}Constructions}{8}
\contentsline {section}{\numberline {6}Exercises 1}{10}
\contentsline {section}{\numberline {7}Contractions}{11}
\contentsline {section}{\numberline {8}Functions}{12}
\contentsline {section}{\numberline {9}Pointers}{13}
\contentsline {section}{\numberline {10}Strings}{15}
\contentsline {section}{\numberline {11}Exercises 2}{19}
\contentsline {section}{\numberline {12}Keywords, Operators and Declarations}{23}
\contentsline {subsection}{\numberline {12.1}Keywords}{23}
\contentsline {subsection}{\numberline {12.2}Operators}{24}
\contentsline {subsection}{\numberline {12.3}Declarations}{24}
\contentsline {section}{\numberline {13}Memory Allocation}{25}
\contentsline {section}{\numberline {14}Input/Output}{28}
\contentsline {subsection}{\numberline {14.1}File I/O under Unix}{28}
\contentsline {subsection}{\numberline {14.2}Interactive}{30}
\contentsline {subsubsection}{\numberline {14.2.1}Output}{30}
\contentsline {subsubsection}{\numberline {14.2.2}Input}{30}
\contentsline {section}{\numberline {15}Source File organisation}{31}
\contentsline {subsection}{\numberline {15.1}Preprocesser Facilities}{31}
\contentsline {subsection}{\numberline {15.2}Multiple Source Files}{32}
\contentsline {subsection}{\numberline {15.3}Make}{33}
\contentsline {section}{\numberline {16}Debugging}{34}
\contentsline {subsection}{\numberline {16.1}Utilities}{34}
\contentsline {subsection}{\numberline {16.2}Some Common mistakes}{35}
\contentsline {subsubsection}{\numberline {16.2.1}Miscellaneous}{35}
\contentsline {subsubsection}{\numberline {16.2.2}declaration mismatch}{39}
\contentsline {subsubsection}{\numberline {16.2.3}malloc}{40}
\contentsline {subsubsection}{\numberline {16.2.4}Find the bug}{41}
\contentsline {section}{\numberline {17}Exercises 3}{42}
\contentsline {section}{\numberline {18}More information}{46}
\contentsline {section}{\numberline {A}Examples}{47}
\contentsline {subsection}{\numberline {A.1}Command Line arguments}{47}
\contentsline {subsection}{\numberline {A.2}Using {\ptt qsort}, random numbers and the clock}{47}
\contentsline {subsection}{\numberline {A.3}Calling other programs}{47}
\contentsline {subsection}{\numberline {A.4}Linked Lists}{48}
\contentsline {subsection}{\numberline {A.5}Using pointers instead of arrays}{49}
\contentsline {subsection}{\numberline {A.6}A data filter}{50}
\contentsline {subsection}{\numberline {A.7}Reading Directories}{52}
\contentsline {subsection}{\numberline {A.8}Queens: recursion and bit arithmetic}{52}
\contentsline {section}{\numberline {B}More on Multidimensional Arrays and Pointers}{53}
\contentsline {section}{\numberline {C}Signals and error handling}{55}
\contentsline {section}{\numberline {D}{\ptt ANSI C}}{56}
\contentsline {subsection}{\numberline {D.1}Converting to {\ptt ANSI C}}{57}
\contentsline {section}{\numberline {E}Numerical Analysis}{58}
\contentsline {section}{\numberline {F}Fortran and C}{59}
\contentsline {section}{\numberline {G}Calling Fortran from C}{60}
love-tex/warning.px 100644 0 0 370 5600705276 12705 0 ustar root root #define warning_width 13
#define warning_height 13
static char warning_bits[] = {
0x40, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0x10, 0x01, 0x50, 0x01, 0x48, 0x02,
0x48, 0x02, 0x44, 0x04, 0x44, 0x04, 0x02, 0x08, 0x42, 0x08, 0x01, 0x10,
0xfe, 0x0f};
Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!
This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.
But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/