diff options
Diffstat (limited to 'reference/C/CONTRIB/SAWTELL')
-rw-r--r-- | reference/C/CONTRIB/SAWTELL/Makefile.am | 5 | ||||
-rw-r--r-- | reference/C/CONTRIB/SAWTELL/Makefile.in | 410 | ||||
-rwxr-xr-x | reference/C/CONTRIB/SAWTELL/c-lesson.1 | 177 | ||||
-rwxr-xr-x | reference/C/CONTRIB/SAWTELL/c-lesson.2 | 233 | ||||
-rwxr-xr-x | reference/C/CONTRIB/SAWTELL/c-lesson.3 | 629 | ||||
-rwxr-xr-x | reference/C/CONTRIB/SAWTELL/c-lesson.4 | 313 | ||||
-rwxr-xr-x | reference/C/CONTRIB/SAWTELL/c-lesson.5 | 291 | ||||
-rwxr-xr-x | reference/C/CONTRIB/SAWTELL/c-lesson.6 | 331 | ||||
-rwxr-xr-x | reference/C/CONTRIB/SAWTELL/c-lesson.7 | 161 | ||||
-rwxr-xr-x | reference/C/CONTRIB/SAWTELL/c-lesson.8 | 502 | ||||
-rwxr-xr-x | reference/C/CONTRIB/SAWTELL/c-lesson.9 | 433 | ||||
-rw-r--r-- | reference/C/CONTRIB/SAWTELL/intro.html | 24 |
12 files changed, 3509 insertions, 0 deletions
diff --git a/reference/C/CONTRIB/SAWTELL/Makefile.am b/reference/C/CONTRIB/SAWTELL/Makefile.am new file mode 100644 index 0000000..f4e2289 --- /dev/null +++ b/reference/C/CONTRIB/SAWTELL/Makefile.am @@ -0,0 +1,5 @@ +EXTRA_DIST = $(wildcard *.html) $(wildcard c-lesson.*) +docs_DATA = $(EXTRA_DIST) + +docsdir = $(kde_htmldir)/en/kdevelop/$(subdir) + diff --git a/reference/C/CONTRIB/SAWTELL/Makefile.in b/reference/C/CONTRIB/SAWTELL/Makefile.in new file mode 100644 index 0000000..37813f0 --- /dev/null +++ b/reference/C/CONTRIB/SAWTELL/Makefile.in @@ -0,0 +1,410 @@ +# KDE tags expanded automatically by am_edit - $Revision: 1.2 $ +# Makefile.in generated automatically by automake 1.5 from Makefile.am. + +# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 +# Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +SHELL = @SHELL@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ + +bindir = @bindir@ +sbindir = @sbindir@ +libexecdir = @libexecdir@ +datadir = @datadir@ +sysconfdir = @sysconfdir@ +sharedstatedir = @sharedstatedir@ +localstatedir = @localstatedir@ +libdir = @libdir@ +infodir = @infodir@ +mandir = @mandir@ +includedir = @includedir@ +oldincludedir = /usr/include +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +top_builddir = ../../../.. + +ACLOCAL = @ACLOCAL@ +AUTOCONF = @AUTOCONF@ +AUTOMAKE = @AUTOMAKE@ +AUTOHEADER = @AUTOHEADER@ + +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_HEADER = $(INSTALL_DATA) +transform = @program_transform_name@ +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_alias = @build_alias@ +build_triplet = @build@ +host_alias = @host_alias@ +host_triplet = @host@ +target_alias = @target_alias@ +target_triplet = @target@ +AMTAR = @AMTAR@ +ARTSCCONFIG = @ARTSCCONFIG@ +AS = @AS@ +AUTODIRS = @AUTODIRS@ +AWK = @AWK@ +CC = @CC@ +CONF_FILES = @CONF_FILES@ +CPP = @CPP@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +DCOPIDL = @DCOPIDL@ +DCOPIDL2CPP = @DCOPIDL2CPP@ +DCOP_DEPENDENCIES = @DCOP_DEPENDENCIES@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DPMSINC = @DPMSINC@ +DPMSLIB = @DPMSLIB@ +EXEEXT = @EXEEXT@ +GCJ = @GCJ@ +GCJFLAGS = @GCJFLAGS@ +GLINC = @GLINC@ +GLLIB = @GLLIB@ +GMSGFMT = @GMSGFMT@ +IDL = @IDL@ +IDL_DEPENDENCIES = @IDL_DEPENDENCIES@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +JAR = @JAR@ +JAVAC = @JAVAC@ +JAVAH = @JAVAH@ +JVMLIBS = @JVMLIBS@ +KDECONFIG = @KDECONFIG@ +KDE_CXXFLAGS = @KDE_CXXFLAGS@ +KDE_EXTRA_RPATH = @KDE_EXTRA_RPATH@ +KDE_INCLUDES = @KDE_INCLUDES@ +KDE_LDFLAGS = @KDE_LDFLAGS@ +KDE_PLUGIN = @KDE_PLUGIN@ +KDE_RPATH = @KDE_RPATH@ +KDE_USE_CLOSURE_FALSE = @KDE_USE_CLOSURE_FALSE@ +KDE_USE_CLOSURE_TRUE = @KDE_USE_CLOSURE_TRUE@ +KDE_USE_FINAL_FALSE = @KDE_USE_FINAL_FALSE@ +KDE_USE_FINAL_TRUE = @KDE_USE_FINAL_TRUE@ +KDE_XSL_STYLESHEET = @KDE_XSL_STYLESHEET@ +LIBCOMPAT = @LIBCOMPAT@ +LIBCRYPT = @LIBCRYPT@ +LIBDL = @LIBDL@ +LIBGEN = @LIBGEN@ +LIBJPEG = @LIBJPEG@ +LIBMICO = @LIBMICO@ +LIBOBJS = @LIBOBJS@ +LIBPNG = @LIBPNG@ +LIBPTHREAD = @LIBPTHREAD@ +LIBPYTHON = @LIBPYTHON@ +LIBQIMGIO = @LIBQIMGIO@ +LIBRESOLV = @LIBRESOLV@ +LIBSHADOW = @LIBSHADOW@ +LIBSM = @LIBSM@ +LIBSOCKET = @LIBSOCKET@ +LIBTIFF = @LIBTIFF@ +LIBTOOL = @LIBTOOL@ +LIBUCB = @LIBUCB@ +LIBUTIL = @LIBUTIL@ +LIBXINERAMA = @LIBXINERAMA@ +LIBZ = @LIBZ@ +LIB_KAB = @LIB_KAB@ +LIB_KDECORE = @LIB_KDECORE@ +LIB_KDEUI = @LIB_KDEUI@ +LIB_KFILE = @LIB_KFILE@ +LIB_KFM = @LIB_KFM@ +LIB_KFORMULA = @LIB_KFORMULA@ +LIB_KHTML = @LIB_KHTML@ +LIB_KIMGIO = @LIB_KIMGIO@ +LIB_KIO = @LIB_KIO@ +LIB_KPARTS = @LIB_KPARTS@ +LIB_KSPELL = @LIB_KSPELL@ +LIB_KSYCOCA = @LIB_KSYCOCA@ +LIB_KWRITE = @LIB_KWRITE@ +LIB_QT = @LIB_QT@ +LIB_SMB = @LIB_SMB@ +LIB_X11 = @LIB_X11@ +LN_S = @LN_S@ +MCOPIDL = @MCOPIDL@ +MEINPROC = @MEINPROC@ +MICO_INCLUDES = @MICO_INCLUDES@ +MICO_LDFLAGS = @MICO_LDFLAGS@ +MOC = @MOC@ +MSGFMT = @MSGFMT@ +NOOPT_CXXFLAGS = @NOOPT_CXXFLAGS@ +NOREPO = @NOREPO@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PAMLIBS = @PAMLIBS@ +PASSWDLIBS = @PASSWDLIBS@ +PYTHONINC = @PYTHONINC@ +PYTHONLIB = @PYTHONLIB@ +PYTHONMODDIR = @PYTHONMODDIR@ +QT_INCLUDES = @QT_INCLUDES@ +QT_LDFLAGS = @QT_LDFLAGS@ +RANLIB = @RANLIB@ +REPO = @REPO@ +SETUIDFLAGS = @SETUIDFLAGS@ +STRIP = @STRIP@ +TOPSUBDIRS = @TOPSUBDIRS@ +UIC = @UIC@ +UIC_TR = @UIC_TR@ +USER_INCLUDES = @USER_INCLUDES@ +USER_LDFLAGS = @USER_LDFLAGS@ +USE_EXCEPTIONS = @USE_EXCEPTIONS@ +USE_RTTI = @USE_RTTI@ +USE_THREADS = @USE_THREADS@ +VERSION = @VERSION@ +XGETTEXT = @XGETTEXT@ +XPMINC = @XPMINC@ +XPMLIB = @XPMLIB@ +X_EXTRA_LIBS = @X_EXTRA_LIBS@ +X_INCLUDES = @X_INCLUDES@ +X_LDFLAGS = @X_LDFLAGS@ +X_PRE_LIBS = @X_PRE_LIBS@ +all_includes = @all_includes@ +all_libraries = @all_libraries@ +am__include = @am__include@ +am__quote = @am__quote@ +idldir = @idldir@ +install_sh = @install_sh@ +jni_includes = @jni_includes@ +kde_appsdir = @kde_appsdir@ +kde_bindir = @kde_bindir@ +kde_confdir = @kde_confdir@ +kde_datadir = @kde_datadir@ +kde_htmldir = @kde_htmldir@ +kde_icondir = @kde_icondir@ +kde_includes = @kde_includes@ +kde_libraries = @kde_libraries@ +kde_libs_htmldir = @kde_libs_htmldir@ +kde_libs_prefix = @kde_libs_prefix@ +kde_locale = @kde_locale@ +kde_mimedir = @kde_mimedir@ +kde_moduledir = @kde_moduledir@ +kde_qtver = @kde_qtver@ +kde_servicesdir = @kde_servicesdir@ +kde_servicetypesdir = @kde_servicetypesdir@ +kde_sounddir = @kde_sounddir@ +kde_templatesdir = @kde_templatesdir@ +kde_wallpaperdir = @kde_wallpaperdir@ +micodir = @micodir@ +qt_includes = @qt_includes@ +qt_libraries = @qt_libraries@ +x_includes = @x_includes@ +x_libraries = @x_libraries@ + +EXTRA_DIST = $(wildcard *.html) $(wildcard c-lesson.*) +docs_DATA = $(EXTRA_DIST) + +docsdir = $(kde_htmldir)/en/kdevelop/$(subdir) +subdir = reference/C/CONTRIB/SAWTELL +mkinstalldirs = $(SHELL) $(top_srcdir)/admin/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +DIST_SOURCES = +DATA = $(docs_DATA) + +DIST_COMMON = Makefile.am Makefile.in +#>- all: all-am +#>+ 1 +all: docs-am all-am + +.SUFFIXES: + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +distclean-libtool: + -rm -f libtool +$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) +#>- cd $(top_srcdir) && \ +#>- $(AUTOMAKE) --gnu reference/C/CONTRIB/SAWTELL/Makefile +#>+ 3 + cd $(top_srcdir) && \ + $(AUTOMAKE) --gnu reference/C/CONTRIB/SAWTELL/Makefile + cd $(top_srcdir) && perl admin/am_edit reference/C/CONTRIB/SAWTELL/Makefile.in +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + cd $(top_builddir) && \ + CONFIG_HEADERS= CONFIG_LINKS= \ + CONFIG_FILES=$(subdir)/$@ $(SHELL) ./config.status +uninstall-info-am: +install-docsDATA: $(docs_DATA) + @$(NORMAL_INSTALL) + $(mkinstalldirs) $(DESTDIR)$(docsdir) + @list='$(docs_DATA)'; for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + f="`echo $$p | sed -e 's|^.*/||'`"; \ + echo " $(INSTALL_DATA) $$d$$p $(DESTDIR)$(docsdir)/$$f"; \ + $(INSTALL_DATA) $$d$$p $(DESTDIR)$(docsdir)/$$f; \ + done + +uninstall-docsDATA: + @$(NORMAL_UNINSTALL) + @list='$(docs_DATA)'; for p in $$list; do \ + f="`echo $$p | sed -e 's|^.*/||'`"; \ + echo " rm -f $(DESTDIR)$(docsdir)/$$f"; \ + rm -f $(DESTDIR)$(docsdir)/$$f; \ + done +tags: TAGS +TAGS: + + +#>- DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +#>+ 4 +KDE_DIST=intro.html c-lesson.1 c-lesson.2 c-lesson.3 c-lesson.4 c-lesson.5 c-lesson.6 c-lesson.7 c-lesson.8 c-lesson.9 + +DISTFILES= $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) $(KDE_DIST) + + +top_distdir = ../../../.. +distdir = $(top_distdir)/$(PACKAGE)-$(VERSION) + +distdir: $(DISTFILES) + @for file in $(DISTFILES); do \ + if test -f $$file; then d=.; else d=$(srcdir); fi; \ + dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test "$$dir" != "$$file" && test "$$dir" != "."; then \ + $(mkinstalldirs) "$(distdir)/$$dir"; \ + fi; \ + if test -d $$d/$$file; then \ + cp -pR $$d/$$file $(distdir) \ + || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(DATA) + +installdirs: + $(mkinstalldirs) $(DESTDIR)$(docsdir) + +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -rm -f Makefile $(CONFIG_CLEAN_FILES) stamp-h stamp-h[0-9]* + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +#>- clean: clean-am +#>+ 1 +clean: kde-rpo-clean clean-am + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-am + +distclean-am: clean-am distclean-generic distclean-libtool + +dvi: dvi-am + +dvi-am: + +info: info-am + +info-am: + +install-data-am: install-docsDATA + +install-exec-am: + +install-info: install-info-am + +install-man: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +uninstall-am: uninstall-docsDATA uninstall-info-am + +.PHONY: all all-am check check-am clean clean-generic clean-libtool \ + distclean distclean-generic distclean-libtool distdir dvi \ + dvi-am info info-am install install-am install-data \ + install-data-am install-docsDATA install-exec install-exec-am \ + install-info install-info-am install-man install-strip \ + installcheck installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-generic \ + mostlyclean-libtool uninstall uninstall-am uninstall-docsDATA \ + uninstall-info-am + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: + +#>+ 2 +docs-am: + +#>+ 6 +force-reedit: + cd $(top_srcdir) && \ + $(AUTOMAKE) --gnu reference/C/CONTRIB/SAWTELL/Makefile + cd $(top_srcdir) && perl admin/am_edit reference/C/CONTRIB/SAWTELL/Makefile.in + + +#>+ 2 +final: + $(MAKE) all-am +#>+ 2 +final-install: + $(MAKE) install-am +#>+ 2 +no-final: + $(MAKE) all-am +#>+ 2 +no-final-install: + $(MAKE) install-am +#>+ 3 +cvs-clean: + $(MAKE) -f $(top_srcdir)/admin/Makefile.common cvs-clean + +#>+ 3 +kde-rpo-clean: + -rm -f *.rpo diff --git a/reference/C/CONTRIB/SAWTELL/c-lesson.1 b/reference/C/CONTRIB/SAWTELL/c-lesson.1 new file mode 100755 index 0000000..a7fdeb7 --- /dev/null +++ b/reference/C/CONTRIB/SAWTELL/c-lesson.1 @@ -0,0 +1,177 @@ + +This archive contains a complete course for you to learn the 'C' computer +language itself. + +The language used is correct conversational English, I have written the +lessons using the same language constructions which I would use if I were +teaching you directly. + +An outline of the course is available for you to read below +The course is intended to demonstrate the language +itself and a selection of the simpler standard library functions. + +I have assumed that you have had sufficient exposure to computing +to be able to use a programmer's editor of your choice and are +confident in the use of the command line interpreter, whether it +be a unix shell, or a DOS ( shudder :-) prompt. Some knowledge, +of computers and the jargon is assumed, but complicated concepts are +fully explained. In other words the intent is to teach 'C' per se, +not 'the fundamentals of how to program a computer using 'C' as +a teaching medium.' + +'C' is not a computer language for rank beginners. Start with +an interpretive language and proceed to a compiled language +which has an extensive error message vocabulary and run-time +checking facilities. In the interests of speed of execution 'C' +does very little to protect you from yourself! + +Throughout the course the fact that a compiler is a translater +from a high level language to assembler code is kept to the fore, +you are frequently advised to examine the assembler code which is +output by the compiler. Some minimal knowledge of computer architecture +is therefore assumed. + +Whilst I have taken considerable care to ensure that this material is +free of errors I am well aware that to err is a common human failing, +and in this I don't claim to be different from anybody else. +Therefore your gentle critique is welcome together with notification +of any factual errors. + +It is planned to make the lessons available as a printed book, +complete with a programme diskette if there is sufficient interest. + + Syllabus for the 'C' Language Course. + + + 1 a) Historical introduction to the Language. + + b) Demonstration of a very simple program. + + c) Brief explanation of how the computer turns + your program text into an executing program. + + d) The basic differences between 'C' and other languages. + The advantages and disadvantages. + + We make the assumption that you are able to turn on your machine, + use the Operating System at the Control Line Interpreter prompt + "$ ", "c:>" or whatever, and to use an editor to enter program text. + + + 2 a) How the 'C' language arranges for the storage of data. + An explanation of the keywords associated with data. + The storage classes:- static auto volatile const. + The variable types:- char int long float double + The meaning of:- signed unsigned + + b) Introduction to the concept of pointers. + + c) Explanation of reading from the keyboard and writing to the screen. + i.e. printf and scanf, the print formatted and scan formatted + functions. + + d) The use of arguments to the main() function, argc argv env. + + e) A simple program to format text. + + + 3 Structures, arrays and pointers. + + a) Explanation of more coplex data structures. + b) Programs which demonstrate uses of pointers. + + 4 The operators of the language, arithmetic, pointer, logical, bitwise. + + a) Precedence. + b) The unique bit and shifting operators. + ( for a high level language ) + + 5 a) The Preprocesser. + b) Header files + + What they are and what you put in them, both your own and + those provided by the 'C' compiler vendor. + + A simple title which includes all sorts of things, + both very useful and a number of traps. + + 6 The library, why we have them and some of the more useful routines. + + a) How to read the book. + b) The string functions as an example. + + 7 a) Mistakes and how avoid making them. + b) Debugging strategies. + c) The assert macro. + + 8 a) More on the representation of data vis. struct, typdef. + + b) Tables of all sorts. + Arrays of structures. + Pre-initialisation of data structures. + ( Including jump or dispatch tables ) + The bit-field. + + c) Use of header files in this. + + + 9 a) The control structures of the language, what (not) to use and when. + + + 10 a) File IO + + This is an enormous subject and we we will + really only just scratch on the surface. + + + 11 a) Lint, and more on errors / bugs and how to avoid them. + + + 12 The stack and a quick dip into assembler + + a) A study of the function calling mechanism used by most 'C' + compilers and the effect on compiler output code of using + the register storage class and the optimiser. + + 13 The heap. + + a) The 'heap', it's management, malloc(), calloc() and free(). + + + 14 Portability Issues. + + a) Defaults for storage sizes. + b) 'endianism'. Yes, there are big-endian and little-endian computers! + c) Functions which can be called with a variable number of arguments. + + + 15 Sample programs. + + Much is to be gained from examining public domain packages + examining the code and reviewing the author's style. + We will look at a number of functions and complete packages. + in particular we will examine a number of sorting functions, + a multi-threading technique, queues, lists, hashing, and trees. + + + /* ----------------------------------------- */ + +Copyright notice:- + +(c) 1993 Christopher Sawtell. + +I assert the right to be known as the author, and owner of the +intellectual property rights of all the files in this material, +except for the quoted examples which have their individual +copyright notices. Permission is granted for onward copying, +but not modification, of this course and its use for personal +study only, provided all the copyright notices are left in the +text and are printed in full on any subsequent paper reproduction. + +-- + +----------------------------------------------------------------------+ + | NAME Christopher Sawtell | + | SMAIL 215 Ollivier's Road, Linwood, Christchurch, 8001. New Zealand.| + | EMAIL chris@gerty.equinox.gen.nz | + | PHONE +64-3-389-3200 ( gmt +13 - your discretion is requested ) | + +----------------------------------------------------------------------+ diff --git a/reference/C/CONTRIB/SAWTELL/c-lesson.2 b/reference/C/CONTRIB/SAWTELL/c-lesson.2 new file mode 100755 index 0000000..7fd15fd --- /dev/null +++ b/reference/C/CONTRIB/SAWTELL/c-lesson.2 @@ -0,0 +1,233 @@ + Lesson One. + +Some Historical Background. + +The 'C' programming language was designed and developed by Brian Kernighan, and +Dennis Ritchie at The Bell Research Labs. 'C' is a Language specifically +created +in order to allow the programmer access to almost all of the machine's +internals +- registers, I/O slots and absolute addresses. However, at the same time, +'C' allows for as much data hiding and programme text modularisation as is +needed to allow very complex multi-programmer projects to be constructed in an +organised and timely fashion. During the early 1960s computer Operating Systems +started to become very much more complex with the introduction of +multi-terminal +and multi-process capabilities. Prior to this time Operating Systems had been +carefully and laboriously crafted using assembler codes, and many programming +teams realised that in order to have a working o/s in anything like a +reasonable time this was now longer economically feasible. This then was the +motivation to produce the 'C' Language, which was first implemented in +assembler on a Digital Equipment Corporation PDP-7. Of course once a simple +assembler version was working it was possible to rewrite the compiler in 'C' +itself. This was done in short order and therefore as soon as the PDP-11 was +introduced by DEC it was only necessary to change the code generator section +of the compiler and the new machine had a compiler in just a few weeks. 'C' was +then used to implement the UNIX o/s. This means, that a complete UNIX can be +transported, or to use the simple jargon of today; 'ported to a new machine in +literally just a few months by a small team of competent programmers. + +Enough of the past. Lets see the various actions, or compilation phases through +which the `C' compilation system has to go in order that your file of `C' +program text can be converted working program. + +Assuming that you are able to work an editor and can enter a script and create +a file. Please enter the following tiny program. + +#ident "@(#) Hello World - my first program" + +#include <stdio.h> + +char *format = "%s", + *hello = "Hello World...\n"; + +main() +{ + printf ( format, hello ); + } + +Now save it in a file called hello.c. Lower case is allowed - encouraged, no +less - under the UNIX operating system. + +Now type: + +cc -o hello hello.c + +The computer will apparently pause for a few moments and then the +Shell, or Command Line Interpreter prompt will re-appear. + +Now type: + +hello + +Lo and behold the computer will print + +Hello World... + +Let's just look at what the computer did during the little pause. + +The first action is to activate a preliminary process called the pre-processor. +In the case of hello.c all it does is to replace the line + +#include <stdio.h> + +with the file stdio.h from the include files library. The file stdio.h provides +us with a convenient way of telling the compiler that all the i/o functions +exist. There are a few other little things in stdio.h but they need not +concern us at this stage. + +In order to see what the pre-processor actually outputs, you might like to +issue the command: + +cc -P hello.c + +The 'cc' command will activate the 'C' compilation system and the -P option +will stop the compilation process after the pre-processing stage, and another +file will have appeared in your directory. Have a look, find hello.i and use +the editor in view mode to have a look at it. So issue the command: + +view hello.i + +You will see that a number of lines of text have been added at the front of the +hello.c program. What's all this stuff? Well, have a look in the file called +/usr/include/stdio.h again using the view command. + +view /usr/include/stdio.h + +Look familiar? + +Now the next stage of getting from your program text to an executing program is +the compilation of your text into an assembler code program. After all that is +what a compiler is for - to turn a high level language script into a program. +Lets see what happens by issuing the command + +cc -S hello.c + +Once again there is another file in your directory - this time with a .s +suffix. + +Lets have a look at it in the same way as the .i file + +view hello.s + +You will doubtless notice a few recognizable symbols and what appears to be a +pile of gibberish. The gibberish is in fact the nmemonics for the machine +instructions which are going to make the computer do what you have programmed +it to do. + +Now this assembler code has to be turned into machine instructions. +To do this issue the command. + +cc -g -c hello.s + +Now, yet again there is another file in your directory - this time the suffix +is ".o". This file is called the object file. It contains the machine +instructions corresponding exactly to the nmemonic codes in the .s file. +If you wish you can look at these machine codes using one of the commands +available to examine object files. + +dis -L -t .data hello.o >hello.dis + +The output from these commands won't be very meaningful to you at this stage, +the purpose of asking you to use them is merely to register in your mind the +fact that an object file is created as a result of the assembly process. + +The next stage in the compilation process is called by a variety of names - +"loading", "linking", "link editing". What happens is that the machine +instructions in the object file ( .o ) are joined to many more instructions +selected from an enormous collection of functions in a library. This phase of +the compilation process is invoked by the command:- + +cc -o hello hello.o + +Now, at last, you have a program to execute! So make it do it's thing by +putting the name of the executable file as a response to the Shell or Command +Line Interpreter prompt. + +hello + +Presto, the output from your program appears on the screen. + +Hello World... + +You are now allowed to rejoice and have a nice warm fuzzy to hold! +You have successfully entered a `C' program, compiled it, linked it, and +finally, executed it! + +Having gone through all the various stages of editing, pre-processing, +compiling, assembling, linking, and finally executing, by hand as it were, you +can now rest assured that all the stages are automated by the 'cc' command, and +you can forget how to invoke them! Just remember that the computer has to do +them in order for you to have a program to execute. + +The single command you use to activate the C Compiler is: + +cc -o hello hello.c + +The word after the -o option is the name of the executable file, if you don't +provide a name here the compiler dreams up the name "a.out". The source file +MUST have the .c extension otherwise the compiler complains and stops working. + +Notes: + + The command names used in the above text are those of standard UNIX, + Your particular system may well use a different name for the 'C' compiler. + bcc - for Borland 'C'. + gcc - GNU 'C', which is standard on the Linux operating system. + lc - Lattice 'C', available on IBM and clone P.C.s as well as the Amiga. + Check in the Documentation which came with your compiler. + The same notions apply to the text editor. + +Differences between 'C' and other languages. + +In the years since 'C' was developed it has changed remarkable little. +This fact is a bouquet to the authors, who had the vision and understanding to +create a language which has endured so well. The strengths and weaknesses +should be pointed out here. + +The big plus is that it is possible to do everything ( well at least 99.9% ) in +'C' while other languages compel you to write a procedure, subroutine or +function in assembler code. + +'C' has very good facilities for creating tables of constant data within the +source file. + +'C' doesn't do very much to protect you from yourself. This means that the +resulting code executes faster than most other high level languages, but a much +greater degree of both care and understanding is demanded from the programmer. + +'C' is not a closely typed language, although the newer compilers are offering +type checking as part of the language itself as opposed to having to use a +separate program for mechanised debugging. + +'C' is a small language with very few intrinsic operations. +All the heavy work is done by explicit library function calls. + +'C' allows you to directly and conveniently access most of the internals of +the machine ( the memory, input output slots, and CPU registers ) from the +language without having to resort to assembler code. + +'C' compilers have an optimisation phase which can be invoked if desired. +The output code can be optimised for either speed or memory usage. The code +will be just as good as that produced by an assembly code programmer of normal +skill - real guru programmers can do only slightly better. + +Copyright notice:- + +(c) 1993 Christopher Sawtell. + +I assert the right to be known as the author, and owner of the +intellectual property rights of all the files in this material, +except for the quoted examples which have their individual +copyright notices. Permission is granted for onward copying, +but not modification, of this course and its use for personal +study only, provided all the copyright notices are left in the +text and are printed in full on any subsequent paper reproduction. + +-- + +----------------------------------------------------------------------+ + | NAME Christopher Sawtell | + | SMAIL 215 Ollivier's Road, Linwood, Christchurch, 8001. New Zealand.| + | EMAIL chris@gerty.equinox.gen.nz | + | PHONE +64-3-389-3200 ( gmt +13 - your discretion is requested ) | + +----------------------------------------------------------------------+ diff --git a/reference/C/CONTRIB/SAWTELL/c-lesson.3 b/reference/C/CONTRIB/SAWTELL/c-lesson.3 new file mode 100755 index 0000000..8d6dac2 --- /dev/null +++ b/reference/C/CONTRIB/SAWTELL/c-lesson.3 @@ -0,0 +1,629 @@ + Lesson 2 + + Data Storage Concepts. + + It has been stated that "data + algorithms = programs". + This Lesson deals with with the first part of the addition sum. + + All information in a computer is stored as numbers represented using the +binary number system. The information may be either program instructions or +data elements. The latter are further subdivided into several different types, +and stored in the computer's memory in different places as directed by the +storage class used when the datum element is defined. + +These types are: + + a) The Character. + + This is a group of 8 data bits and in 'C' represents either + a letter of the Roman alphabet, or a small integer in the range of 0 + through to +255. So to arrange for the compiler to give you a named + memory area in which to place a single letter you would "say": + + char letter; + + at the beginning of a program block. You should be aware that + whether or not a char is signed or unsigned is dependant + on the design of the processor underlying your compiler. + In particular, note that both the PDP-11, and VAX-11 made by + Digital Equipment Corporation have automatic sign extention of +char. + This means that the range of char is from -128 through to +127 + on these machines. Consult your hardware manual, there may be + other exceptions to the trend towards unsigned char as the +default. + + This test program should clear things up for you. + +/* ----------------------------------------- */ + +#ident "@(#) - Test char signed / unsigned."; + +#include <stdio.h> + +main() +{ + char a; + unsigned char b; + + a = b = 128; + a >>= 1; + b >>= 1; + printf ( "\nYour computer has %ssigned char.\n\n", a == b ? "un" : "" ); + } + +/* ----------------------------------------- */ + + Here ( Surprise! Surprise! ) is its output on a machine which has + unsigned chars. + +Your computer has unsigned char. + + Cut this program out of the news file. Compile and execute it on + your computer in order to find out if you have signed or +unsigned char. + + b) The Integers. + + As you might imagine this is the storage type in which to store whole + numbers. There are two sizes of integer which are known as short and long. + The actual number of bits used in both of these types is Implementation + Dependent. This is the way the jargonauts say that it varies from computer + to computer. Almost all machines with a word size larger than sixteen bits + have the the long int fitting exactly into a machine word and +a short int + represented by the contents of half a word. It's done this way because + most machines have instructions which will perform arithmetic +efficiently + on both the complete machine word as well as the half-word. +For the + sixteen bit machines, the long integer is two machine words +long, + and the short integer is one. + + short int smaller_number; + long int big_number; + + Either of the words short or long may be omitted as a default is + provided by the compiler. Check your compiler's documentation +to see + which default you have been given. Also you should be aware +that some + compilers allow the you to arrange for the integers declared +with just + the word "int" to be either short or long. The range for a +short int on + a small computer is -32768 through to +32767, and for a long +int + -4294967296 through to +4294967295. + + c) The Real Numbers. + + Sometimes known as floating point numbers this number representation + allows us to store values such as 3.141593, or -56743.098. So, using + possible examples from a ship design program you declare floats and + doubles like this: + + float length_of_water_line; /* in meters */ + double displacement; /* in grammes */ + + In the same way that the integer type offers two sizes so does the + floating point representation. They are called float and double. Taking + the values from the file /usr/include/values.h the ranges which can be + represented by float and double are: + + MAXFLOAT 3.40282346638528860e+38 + MINFLOAT 1.40129846432481707e-45 + MAXDOUBLE 1.79769313486231470e+308 + MINDOUBLE 4.94065645841246544e-324 + + However you should note that for practical purposes the maximum + number of significant digits that can be represented by a +float + is approximately six and that by a double is twelve. Also you +should + be aware that the above numbers are as defined by the IEEE +floating + point standard and that some older machines and compilers do +not + conform. All small machines bought retail will conform. If you +are + in doubt I suggest that refer to your machine's documentation +for + the whole and exact story! + + + d) Signed and unsigned prefixes. + + For both the character and integer types the declaration can be + preceded by the word "unsigned". This shifts the range so that +0 + is the minimum, and the maximum is twice that of the signed +data + type in question. It's useful if you know that it is +impossible + for the number to go negative. Also if the word in memory is +going + to be used as a bit pattern or a mask and not a number the use +of + unsigned is strongly urged. If it is possible for the sign bit +in + the bit pattern to be set and the program calls for the bit +pattern + to be shifted to the right, then you should be aware that the +sign + bit will be extended if the variable is not declared unsigned. + The default for the "int" types is always "signed", and, as +discussed + above that of the "char" is machine dependent. + + This completes the discussion on the allocation of data types, except to + say that we can, of course, allocate arrays of the simple types simply by + adding a pair of square brackets enclosing a number which is the size of + the array after the variable's name: + + char client_surname[31]; + + This declaration reserves storage for a string of 30 characters plus the + NULL character of value zero which terminates the string. + + Structures. + + Data elements which are logically connected, for example - to use the + example alluded to above - the dimensions and other details about a +sea + going ship, can be collected together as a single data unit called a + struct. One possible way of laying out the struct in the source code +is: + +struct ship /* The word "ship" is known as the structure's "tag". */ +{ + char name[30]; + double displacement; /* in grammes */ + float length_of_water_line; /* in meters */ + unsigned short int number_of_passengers; + unsigned short int number_of_crew; + }; + + Note very well that the above fragment of program text does NOT + allocate any storage, it merely provides a named template to +the + compiler so that it knows how much storage is needed for the + structure. The actual allocation of memory is done either like +this: + +struct ship cunarder; + + Or by putting the name of the struct variable between the "}" +and + the ";" on the last line of the definition. Personally I don't + use this method as I find that the letters of the name tend to +get + "lost" in the - shall we say - amorphous mass of characters +which + make up the definition itself. + + The individual members of the struct can have values assigned to + them in this fashion: + + cunarder.displacement = 97500000000.0; + cunarder.length_of_water_line = 750.0 + cunarder.number_of_passengers = 3575; + cunarder.number_of_crew = 4592; + + These are a couple of files called demo1.c & demo1a.c which contain + small 'C' programs for you to compile. So, please cut them out +of the + news posting file and do so. + + +---------------------------------------------------------------------- +#ident demo1.c /* If your compiler complains about this line, chop it out */ +#include <stdio.h> + +struct ship +{ + char name[31]; + double displacement; /* in grammes */ + float length_of_water_line; /* in meters */ + unsigned short int number_of_passengers; + unsigned short int number_of_crew; + }; + +char *format = "\ +Name of Vessel: %-30s\n\ + Displacement: %13.3f\n\ + Water Line: %5.1f\n\ + Passengers: %4d\n\ + Crew: %4d\n\n"; + +main() +{ + struct ship cunarder; + + cunarder.name = "Queen Mary"; /* This is the bad line. */ + cunarder.displacement = 97500000000.0; + cunarder.length_of_water_line = 750.0 + cunarder.number_of_passengers = 3575; + cunarder.number_of_crew = 4592; + + printf ( format, + cunarder.name, + cunarder.displacement, + cunarder.length_of_water_line, + cunarder.number_of_passengers, + cunarder.number_of_crew + ); + } + +---------------------------------------------------------------------- + + Why is the compiler complaining at line 21? + Well C is a small language and doesn't have the ability to allocate + strings to variables within the program text at run-time. This + program shows the the correct way to copy the string "Queen +Mary", + using a library routine, into the structure. + + +---------------------------------------------------------------------- +#ident demo1a.c /* If your compiler complains about this line, chop it out */ +#include <stdio.h> + +/* +** This is the template which is used by the compiler so that +** it 'knows' how to put your data into a named area of memory. +*/ + +struct ship +{ + char name[31]; + double displacement; /* in grammes */ + float length_of_water_line; /* in meters */ + unsigned short int number_of_passengers; + unsigned short int number_of_crew; + }; + +/* +** This character string tells the printf() function how it is to output +** the data onto the screen. Note the use of the \ character at the end +** of each line. It is the 'continue the string on the next line' flag +** or escape character. It MUST be the last character on the line. +** This technique allows you to produce nicely formatted reports with all the +** ':' characters under each other, without having to count the characters +** in each character field. +*/ + +char *format = "\n\ +Name of Vessel: %-30s\n\ + Displacement: %13.1f grammes\n\ + Water Line: %5.1f metres\n\ + Passengers: %4d\n\ + Crew: %4d\n\n"; + +main() +{ + struct ship cunarder; + + strcpy ( cunarder.name, "Queen Mary" ); /* The corrected line */ + cunarder.displacement = 97500000000.0; + cunarder.length_of_water_line = 750.0; + cunarder.number_of_passengers = 3575; + cunarder.number_of_crew = 4592; + + printf ( format, + cunarder.name, + cunarder.displacement, + cunarder.length_of_water_line, + cunarder.number_of_passengers, + cunarder.number_of_crew + ); + } + +---------------------------------------------------------------------- + + I'd like to suggest that you compile the program demo1a.c and execute it. + +$ cc demo1a.c +$ a.out + +Name of Vessel: Queen Mary + Displacement: 97500000000.0 grammes + Water Line: 750.0 metres + Passengers: 3575 + Crew: 4592 + + Which is the output of our totally trivial program to demonstrate + the use of structures. + + Tip: + + To avoid muddles in your mind and gross confusion in other minds + remember that you should ALWAYS declare a variable using a name which is + long enough to make it ABSOLUTELY obvious what you are talking about. + + Storage Classes. + + The little dissertation above about the storage of variables was + concerned with the sizes of the various types of data. There is + just the little matter of the position in memory of the variables' + storage. + + 'C' has been designed to maximise the the use of memory by allowing you + to re-cycle it automatically when you have finished with it. + A variable defined in this way is known as an 'automatic' one. Although + this is the default behaviour you are allowed to put the word 'auto' in + front of the word which states the variable's type in the definition. + It is quite a good idea to use this so that you can remind yourself + that this variable is, in fact, an automatic one. There are three other + storage allocation methods, 'static' and 'register', and 'const'. + The 'static' method places the variable in main storage for the whole + of the time your program is executing. In other words it kills the + 're-cycling' mechanism. This also means that the value stored there + is also available all the time. The 'register' method is very machine + and implementation dependent, and also perhaps somewhat archaic in + that the optimiser phase of the compilation process does it all for + you. For the sake of completeness I'll explain. Computers have a small + number of places to store numbers which can be accessed very quickly. + These places are called the registers of the Central Processing Unit. + The 'register' variables are placed in these machine registers instead +of + stack or main memory. For program segments which are tiny loops the +speed + at which your program executes can be enhanced quite remarkably. + The optimiser compilation phase places as many of your variables into + registers as it can. However no machine can decide which of the +variables + should be placed in a register, and which may be left in memory, so if + your program has many variables and two or three should be register +ones + then you should specify which ones the compiler. + + All this is dealt with at much greater detail later in the course. + + Pointers. + + 'C' has the very useful ability to set up pointers. These are memory + cells which contain the address of a data element. The variable name is + preceeded by a '*' character. So, to reserve an element of type char +and + a pointer to an element of type char, one would say. + +char c; +char *ch_p; + + I always put the suffix '_p' on the end of all pointer variables + simply so that I can easily remember that they are in fact pointers. + + There is also the companion unary operator '&' which yields the + address of the variable. So to initialize our pointer ch_p to point + at the char c, we have to say. + + ch_p = &c; + + Note very well that the process of indirection can procede to any + desired depth, However it is difficult for the puny brain of a normal + human to conceptualize and remember more that three levels! So be +careful + to provide a very detailed and precise commentry in your program if + you put more than two or three stars. + + + Getting data in and out of your programs. + + As mentioned before 'C' is a small language and there are no intrinsic + operators to either convert between binary numbers and ascii + characters or to transfer information to and fro between the + computer's memory and the peripheral equipment, such as terminals or + disk stores. + + This is all done using the i/o functions declared in the file stdio.h + which you should have examined earlier. Right now we are going to look + at the functions "printf" and "scanf". These two functions together + with their derivatives, perform i/o to the stdin and stdout files, + i/o to nominated files, and internal format conversions. This means + the conversion of data from ascii character strings to binary numbers + and vice versa completely within the computer's memory. It's more + efficient to set up a line of print inside memory and then to send the + whole line to the printer, terminal, or whatever, instead of + "squirting" the letters out in dribs and drabs! + + Study of them will give you understanding of a very convenient way to + talk to the "outside world". + + So, remembering that one of the most important things you learn in + computing is "where to look it up", lets do just that. + If you are using a computer which has the unix operating system, + find your copy of the "Programmer Reference Manual" and turn to the + page printf(3S), alternatively, if your computer is using some other + operating system, then refer to the section of the documentation which + describes the functions in the program library. + + You will see something like this:- + + NAME + printf, fprintf, sprintf - print formatted +output. + + SYNOPSIS + #include <stdio.h> + + int printf ( format [ , arg ] ... ) + char *format; + + int fprintf ( stream, format [ , arg ] ... ) + FILE *stream; + char *format; + + int sprintf ( s, format [ , arg ] ... ) + char *s, *format; + + DESCRIPTION + + etc... etc... + + The NAME section above is obvious isn't it? + + The SYNOPSIS starts with the line #include <stdio.h>. This tells + you that you MUST put this #include line in your 'C' source code + before you mention any of the routines. The rest of the paragraph + tells you how to call the routines. The " [ , arg ] ... " heiroglyph + in effect says that you may have as many arguments here as you wish, + but that you need not have any at all. + + The DESCRIPTION explains how to use the functions. + + Important Point to Note: + + Far too many people ( including the author ) ignore the fact that + the printf family of functions return a useful number which can be + used to check that the conversion has been done correctly, and that + the i/o operation has been completed without error. + + Refer to the format string in the demonstration program above for + an example of a fairly sophisticated formatting string. + + In order to fix the concepts of printf in you mind, you + might care to write a program which prints some text in three ways: + +a) Justified to the left of the page. ( Normal printing. ) +b) Justified to the right of the page. +c) Centred exactly in the middle of the page. + + Suggestions and Hint. + + Set up a data area of text using the first verse of "Quangle" as data. + Here is the program fragment for the data:- + +/* ----------------------------------------- */ + +char *verse[] = +{ + "On top of the Crumpetty Tree", + "The Quangle Wangle sat,", + "But his face you could not see,", + "On account of his Beaver Hat.", + "For his Hat was a hundred and two feet wide.", + "With ribbons and bibbons on every side,", + "And bells, and buttons, and loops, and lace,", + "So that nobody ever could see the face", + "Of the Quangle Wangle Quee.", + NULL + }; + +/* ----------------------------------------- */ + + Cut it out of the news file and use it in a 'C' program file called + verse.c + + Now write a main() function which uses printf alone for (a) & (b) + You can use both printf() and sprintf() in order to create + a solution for (c) which makes a good use of the capabilities + of the printf family. The big hint is that the string controlling + the format of the printing can change dynamically as program execution + proceeds. A possible solution is presented in the file verse.c which is + appended here. I'd like to suggest that you have a good try at making + a program of you own before looking at my solution. + ( One of many I'm sure ) + +/* ----------------------------------------- */ + +#include <stdio.h> + +char *verse[] = +{ + "On top of the Crumpetty Tree", + "The Quangle Wangle sat,", + "But his face you could not see,", + "On account of his Beaver Hat.", + "For his Hat was a hundred and two feet wide.", + "With ribbons and bibbons on every side,", + "And bells, and buttons, and loops, and lace,", + "So that nobody ever could see the face", + "Of the Quangle Wangle Quee.", + NULL + }; + +main() +{ + char **ch_pp; + + /* + ** This will print the data left justified. + */ + + for ( ch_pp = verse; *ch_pp; ch_pp++ ) printf ( "%s\n", *ch_pp ); + printf( "\n" ); + + /* + ** This will print the data right justified. + ** + ** ( As this will print a character in column 80 of + ** the terminal you should make sure any terminal setting + ** which automatically inserts a new line is turned off. ) + */ + + for ( ch_pp = verse; *ch_pp; ch_pp++ ) printf ( "%79s\n", *ch_pp ); + printf( "\n" ); + + /* + ** This will centre the data. + */ + + for ( ch_pp = verse; *ch_pp; ch_pp++ ) + { + int length; + char format[10]; + + length = 40 + strlen ( *ch_pp ) / 2; /* Calculate the +field length */ + sprintf ( format, "%%%ds\n", length ); /* Make a format +string. */ + printf ( format, *ch_pp ); /* Print line of +verse, using */ + } /* generated format +string */ + printf( "\n" ); + } + +/* ----------------------------------------- */ + + If you cheated and looked at my example before even attempting + to have a go, you must pay the penalty and explain fully why + there are THREE "%" signs in the line which starts with a call + to the sprintf function. It's a good idea to do this anyway! + + + So much for printf(). Lets examine it's functional opposite - scanf(), + + Scanf is the family of functions used to input from the outside world + and to perform internal format conversions from character strings to + binary numbers. Refer to the entry scanf(3S) in the Programmer + Reference Manual. ( Just a few pages further on from printf. ) + + The "Important Point to Note" for the scanf family is that the + arguments to the function are all POINTERS. The format string has to + be passed in to the function using a pointer, simply because this + is the way 'C' passes strings, and as the function itself has to store + its results into your program it ( the scanf function ) has to "know" + where you want it to put them. + +Copyright notice:- + +(c) 1993 Christopher Sawtell. + +I assert the right to be known as the author, and owner of the +intellectual property rights of all the files in this material, +except for the quoted examples which have their individual +copyright notices. Permission is granted for onward copying, +but not modification, of this course and its use for personal +study only, provided all the copyright notices are left in the +text and are printed in full on any subsequent paper reproduction. + +-- + +----------------------------------------------------------------------+ + | NAME Christopher Sawtell | + | SMAIL 215 Ollivier's Road, Linwood, Christchurch, 8001. New Zealand.| + | EMAIL chris@gerty.equinox.gen.nz | + | PHONE +64-3-389-3200 ( gmt +13 - your discretion is requested ) | + +----------------------------------------------------------------------+ diff --git a/reference/C/CONTRIB/SAWTELL/c-lesson.4 b/reference/C/CONTRIB/SAWTELL/c-lesson.4 new file mode 100755 index 0000000..a6072e0 --- /dev/null +++ b/reference/C/CONTRIB/SAWTELL/c-lesson.4 @@ -0,0 +1,313 @@ + Lesson 3 + + Arrays and Pointers. + + You can allocate space for an array of elements at compile time with fixed + dimension sizes of any data type, even functions and structs. + So these are legal array definitions: + + char name[30]; /* An array of 30 signed characters. */ + char *strings[50]; /* 50 pointers to strings. */ + unsigned long int *(*func)()[20];/* An array of pointers to functions which +*/ + /* return pointers to unsigned long ints. */ + + You can declare a pointer to point at any type of data element, and as in + the array situation above functions and structs are included. + +struct ship +{ + char name[30]; + double displacement; /* in grammes */ + float length_of_water_line; /* in meters */ + unsigned short int number_of_passengers; + unsigned short int number_of_crew; + }; + + So using the ship concept from Lesson 2 you can declare a pointer to point + at one of the ship structs in an array. + +struct ship *vessel_p; + + Note the use of the suffix "_p". + This is my way of reminding myself that the variable is a pointer. + +struct ship fleet[5]; /* This allocates enough storage for 5 ships' info. +*/ + + Now lets set the pointer to point at the first vessel in the fleet. + + vessel_p = fleet; + + This pointer can be made to point at other ships in the fleet by + incrementing it or doing additive arithmetic on it: + + vessel_p++; /* point a the next ship in the fleet array. */ + vessel_p = fleet + 3; + + Also we can find out the index of the ship in the fleet at which we are + pointing: + + i = vessel_p - fleet; + + It is also legal to find out the separation of two pointers pointing at + elements in an array: + + d = vessel_p - another_vessel_p; /* This gives the separation in elements. */ + + So summarising, pointers may be, incremented, decremented, and subtracted + one from another or have a constant subtracted from them. Any other + mathematical operation is meaningless and not allowed. + + Assembler programmers should note that while the pointer variables contain a + byte machine address, when the arithmetic is done using pointers the +compiler + also issues either a multiply or a divide as well as the add or subtract + instruction so that the result is ALWAYS expressed in elements rather than + bytes. Have a go and write yourself a trivial little program, and have a + look at the compiler ouput code. Lesson 1 told you how! + + When using a pointer to reference a structure we have to use a "pointer + offset" operator in order to access the member of the struct we require: + + vessel_p = fleet; + + vessel_p->name = "Queen Mary"; + vessel_p->displacement = 97500000000.0; + vessel_p->length_of_water_line = 750.0 + vessel_p->number_of_passengers = 3575; + vessel_p->number_of_crew = 4592; + + Remember: + + It's a "." when accessing a struct which is in storage declared in + the program. + + It's a "->" when accessing a struct at which a pointer is pointing. + + Initialisation of arrays. + + 'C' has the facility to initialise variables in a program script. + + Some examples: + + char *qbf = "The quick brown fox jumped over the lazy dogs back"; + + int tic_tac_toe[3][3] = + { + { 1, 2, 3 }, + { 4, 5, 6 }, + { 7, 8, 9 } + }; + + struct ship fleet[2] = + { + { "Queen Elizabeth", 97500000000.0, 750.0, 3575, 4592 }, + { "Queen Mary", 115000000000.0, 875.0, 4500, 5500 } + }; + + Take a careful note of where the commas and semi-colons go ( and don't go )! + + Initialised Tables of Indeterminate Length. + + One nice feature 'C' offers is that it is able to calculate + the amount of storage required for a table by 'looking' at the number + of initialisers. + +char *verse[] = +{ + "On top of the Crumpetty Tree", + "The Quangle Wangle sat,", + "But his face you could not see,", + "On account of his Beaver Hat.", + "For his Hat was a hundred and two feet wide.", + "With ribbons and bibbons on every side,", + "And bells, and buttons, and loops, and lace,", + "So that nobody ever could see the face", + "Of the Quangle Wangle Quee." + NULL + }; + + Note the * character in the definition line. This means that we are going + to make an array of pointers to variables of type char. As there is no + number between the [ ] characters the compiler calculates it for us. + With this kind of set-up it is nice and easy to add extra information + to the table as program development proceeds. The compiler will calculate + the new dimension for you. The point to remember is that the program has to + know - from the contents of the table - that it has come to the end of the + table! So you have to make a special entry which CANNOT under any + circumstances be a real data element. We usually use NULL for this. + The other way is to calculate the size of the table by using the sizeof + operator - Note that although use of sizeof looks like a function call + it is in fact an intrinsic operator of the language. The result is + available at compile time. So one can say:- + + #define SIZE_OF_VERSE sizeof verse + + There is one final initialised data type, the enum. It is a fairly recent + addition to the language. + + enum spectrum { red, orange, yellow, green, blue, indigo, violet } colour; + + In this construct the first symbol is given the value of 0 and for each + following symbol the value is incremented. It is however possible to assign + specific values to the symbols like this: + + enum tub + { anorexic = 65, + slim = 70, + normal = 80, + fat = 95, + obese = 135 + }; + + Some compilers are bright enough to detect that it is an error if an + attempt is made to assign a value to an enum variable which is not in + the list of symbols, on the other hand many are not. Take care! In + practice there is little difference between the enum language construct + and a number of define statements except perhaps aesthetics. Here is + another trivial program which demonstrates the use of enum and a + pre-initialised array. + +#include <stdio.h> + +enum spectrum { red, orange, yellow, green, blue, indigo, violet } colour; + +char *rainbow[] = { "red", "orange", "yellow", "green", + "blue", "indigo", "violet" }; + +main() +{ + for ( colour = red; colour <= violet; colour++ ) + { + printf ( "%s ", rainbow[colour]); + } + printf ( "\n" ); + } + + The output of which is ( not surprisingly ): + +red orange yellow green blue indigo violet + + One quite advanced use of initialised arrays and pointers is the jump or + dispatch table. This is a efficient use of pointers and provides a very much + better ( In my opinion ) method of controlling program flow than a maze + of case or ( heaven forbid ) if ( ... ) goto statements. + + Please cut out this program, read and compile it. + ------------------------------------------------------------------------ + +char *ident = "@(#) tellme.c - An example of using a pointer to a function."; + +#include <stdio.h> +#include <math.h> +#include <sys/errno.h> + +/* +These declarations are not in fact needed as they are all declared extern in +math.h. However if you were to use routines which are not in a library and +therefore not declared in a '.h' file you should declare them. Remember you +MUST declare external routines which return a type other than the int type. + +extern double sin (); +extern double cos (); +extern double tan (); +extern double atof (); +*/ + +struct table_entry +{ + char *name; /* The address of the character string. */ + double (*function)(); /* The address of the entry point of the function. */ + }; + +typedef struct table_entry TABLE; + +double help ( tp ) +TABLE *tp; +{ printf ( "Choose one of these functions:- " ); + fflush ( stdout ); + for ( ; tp -> name; tp++ ) printf ( "%s ", tp -> name ); + printf ( "\nRemember the input is expressed in Radians\n" ); + exit ( 0 ); + return ( 0.0 ); /* Needed to keep some nit-picking dumb compilers happy! */ + } + +/* + * This is the array of pointers to the strings and function entry points. + * Is is initialised at linking time. You may add as many functions as you + * like in here PROVIDED you declare them to be extern, either in some .h + * file or explicitly. + */ + +TABLE interpretation_table [ ] = +{ + { "sin", sin }, + { "tan", tan }, + { "cos", cos }, + { "help", help }, + { NULL, NULL } /* To flag the end of the table. */ + }; + +char *output_format = { "\n %s %s = %g\n" }; +extern int errno; +extern void perror(); + +main( argc, argv ) +int argc; +char **argv; +{ + TABLE *tp; + double x, answer; + + if ( argc > 3 ) + { + errno = E2BIG; + perror ( "tellme" ); + exit ( -1 ); + } + + for (;;) /* This is the way to set up a continuous loop. */ + { + for ( tp = interpretation_table; + ( tp -> name && strcmp ( tp -> name, argv[1] )); + tp++ + ) ; /* Note use of empty for loop to position tp. */ + + if ( tp -> function == help ) (*tp -> function )( interpretation_table ); + if ( tp -> name == NULL ) + { + printf ( "Function %s not implemented yet\n", argv[1] ); + exit ( 1 ); + } + break; /* Leave the loop. */ + } + + x = atof ( argv[2] ); /* Convert the character string to a double. */ + answer = ( *tp -> function )( x );/* Execute the desired function. */ + printf ( output_format, /* Pointer to printf()'s format string. */ + argv[1], /* Pointer to the name of the function. */ + argv[2], /* Pointer to the input number ascii string. */ + answer /* Value ( in double floating point binary ) */ + ); + } + +Copyright notice:- + +(c) 1993 Christopher Sawtell. + +I assert the right to be known as the author, and owner of the +intellectual property rights of all the files in this material, +except for the quoted examples which have their individual +copyright notices. Permission is granted for onward copying, +but not modification, of this course and its use for personal +study only, provided all the copyright notices are left in the +text and are printed in full on any subsequent paper reproduction. + +-- + +----------------------------------------------------------------------+ + | NAME Christopher Sawtell | + | SMAIL 215 Ollivier's Road, Linwood, Christchurch, 8001. New Zealand.| + | EMAIL chris@gerty.equinox.gen.nz | + | PHONE +64-3-389-3200 ( gmt +13 - your discretion is requested ) | + +----------------------------------------------------------------------+ diff --git a/reference/C/CONTRIB/SAWTELL/c-lesson.5 b/reference/C/CONTRIB/SAWTELL/c-lesson.5 new file mode 100755 index 0000000..949fb49 --- /dev/null +++ b/reference/C/CONTRIB/SAWTELL/c-lesson.5 @@ -0,0 +1,291 @@ + +Lesson 4. + + The +operators of the language. + + I have mentioned that 'C' is a small language with most of the heavy +work +being done by explicit calls to library functions. There is however a rich +mix of intrinsic operators which allow you to perform bit level operations, +use pointers, and perform immediate operations on varables. In other words, +most of a machine's instruction set is able to be used in the object program. +At the time when 'C' was designed and first written these were unique for +a high level language. + + Lets start with a discussion about precedence. + + This really means that the compiler puts invisable parentheses into +your expression. Casting your mind back to Arithmetic in the primary school +I expect you remember the nmemonic "My Dear Aunt Sally". The 'C' language +does as well! So the following expression is correct + + 15 + 4 * 11 = 59 + + The compiler has rendered the expression as: + + 15 + ( 4 * 11 ) = 59 + + Now the 'C' language has a much larger collection of operators than +just +Multiply Divide Add Subtract, in fact much too big to try to remember the +precedence of all of them. So my recomendation is to ALWAYS put in the +parentheses, except for simple arithmetic. However, for the sake of +completeness as much as anything else, here is the list. + + First up come what are called the primary-expression operators: + + () Function. + [] Array. + . struct member ( variable ). + -> struct member ( pointer ). + + The unary operators: + + * Indirection via a Pointer. + & Address of Variable. + - Arithmetic Negative. + ! Logical Negation or Not. + ~ Bit-wise One's Complement. + ++ Increment. + -- Decrement. + sizeof Which is self explanitary. + + Now the binary operators: + + Arithmetic Operators. + + * Multiply. My + / Divide. Dear + % Modulo, or Remainder of Integer Division. + + Addition. Aunt + - Subtraction. Sally + + The Shifting Operators. + + >> Bit-wise Shift to the Right. + << Bit-wise Shift to the Left. + + Logical Relation Operators. + + < Less Than. + > Greater Than. + <= Less Than or Equal. + >= Greater Than or Equal. + == Equal. + != Not Equal. + + Bit-wise Boolean Operators. + + & Bit-wise And. + ^ Bit-wise Exclusive-or. + | Bit-wise Or. + + The Logical Operators. + + && Logical And. + || Logical Or. + + The Assignment Operators. ( They all have the same priority. ) + + = The normal assignment operator. + + The Self-referencing Assignment Operators. + + += + -= + *= + /= + %= + >>= + <<= + &= + ^= + |= + + Some explanation is in order here. The machine instructions in your +computer include a suit of what are called "immediate operand" instructions. +These instructions have one of the operands in a register and the other +is either part of the instruction word itself ( if it is numerically small +enough to fit ) or is the next word in the address space "immediately" after +the instruction code word. 'C' makes efficient use of this machine feature +by providing the above set of operations each of which translates directly +to its corresponding machine instruction. When the variable in question is a +'register' one, or the optimiser is in use, the compiler output is just +the one "immediate" machine instruction. Efficiency Personified!!! + + These two lines will make things clearer. + + a = 8; + a += 2; /* The result is 10 */ + + The exclusive-or operation is very useful you can toggle any +combination +of bits in the variable using it. + + a = 7; + a ^= 2; /* Now a is 5 */ + a ^= 2; /* and back to 7. */ + + Naturally, you can use the other operations in exactly the same way, +I'd like to suggest that you make a utterly simplistic little program +and have a look at the assembler code output of the compiler. Don't be +afraid of the assembler codes - they don't bite - and you will see +what I was on about in the paragraph above. + + Historical Note and a couple of Cautions. + + In the Oldend Days when 'C' was first written all the self-referencing +operations had the equals symbol and the operand around the other way. +Until quite recently ( unix system V release 3.0 ) the 'C' compiler had a +compatability mode and could cope with the old style syntax. + + A sample or test program is probably in order here. + +/* ----------------------------------------- */ + +#include <stdio.h> + +char *mes[] = +{ + "Your compiler", + " understands", + " does not understand", + " the old-fashioned self-referencing style." + }; + +main() +{ + int a; + + a = 5; + a=-2; + printf ( "%s %s %s\n", mes [ 0 ], mes [ ( a == -2 ) ? 2 : 1 ], mes [ 3 +] ); + } + +/* ----------------------------------------- */ + + The 'C' compiler issued with unix System V release 3.2 seems to have +( thankfully ) dropped the compatability mode. However a collegue, who +was using an old compiler, and I spent hours trying to find this strange bug! +The cure for the problem is either to put spaces on either side of the '=' sign +or to bracket the unary minus to the operand. + + a=(-2); + a = -2; + +Either is acceptable, and might save you a lot of spleen if sombody tries +to install your work of art program on an ancient machine. + + The other caution is the use of the shifting instructions with signed +and unsigned integers. + + If you shift a signed integer to the right when the sign bit is set +then in all probability the sign will be extended. Once again a little +demo program. Please cut it out of the news file with your editor +and play with it. + +/* ----------------------------------------- */ + +#ident "#(@) shifts.c - Signed / Unsigned integer shifting demo." +#include <stdio.h> + +#define WORD_SIZE ( sizeof ( INTEGER int ) * 8 ) +#define NIBBLE_SIZE 4 +#define NIBBLES_IN_WORD (( WORD_SIZE ) / NIBBLE_SIZE ) +#define SIGN_BIT ( 1 << ( WORD_SIZE - 1 )) + +char *title[] = +{ " Signed Unsigned", + " Signed Unsigned" + }; + +main () +{ + INTEGER int a; + unsigned INTEGER int b, mask; + int ab, i, j, bit_counter, line_counter; + + a = b = SIGN_BIT; + printf ( "%s\n\n", title [ ( WORD_SIZE == 16 ) ? 0 : 1 ] ); + + for ( line_counter = 0; line_counter < WORD_SIZE; line_counter++ ) + { + for ( ab = 0; ab < 2; ab++ ) + { + mask = SIGN_BIT; + for ( i = 0; i < NIBBLES_IN_WORD; i++ ) + { + for ( j = 0; j < NIBBLE_SIZE; j++ ) + { + printf ( "%c", ((( ab ) ? b : a ) & +mask ) ? '1' : '0' ); + mask >>= 1; + } + printf ( " " ); + } + printf ( "%s", ( ab ) ? "\n" : " " ); + if ( ab ) + { + b >>= 1; + } + else + { + a >>= 1; +#if defined(FIX_COMPILER_BUG) +# if (INTEGER == long) + a |= SIGN_BIT; /* This is a work-around for +the 3b2 compiler bug. */ +# endif +#endif + } + } + } + } + +/* ----------------------------------------- */ + + This little program might well produce some interesting surprises on +your machine in the same way it did on mine. I have an AT&T 3b2/400 and +use the K & R style compiler. Interestingly, the above program did what +I expected it to do when the integers were short, the sign bit is extended, +but when the integers are long the sign bit is NOT extended. In this case +the different behaviour is caused by the compiler always issuing a Logical +Shift instruction, when it should issue a Arithmetic Shift instruction for +signed integers and a Logical Shift instructon for unsigned ones. In the +case of the short int the varable is loaded from memory into the register +with a sign extend load instruction, this makes the Logical Shift instruction +right work correctly for short ints, but not for longs. I had to examine +the assember codes output by the compiler in order to discover this. + + Here are the compiler invocation lines. + +cc -olong.shifts -DFIX_COMPILER_BUG -DINTEGER=long shifts.c + + and + +cc -oshort.shifts -DINTEGER=short shifts.c + + Experiment with the "-DFIX_COMPILER_BUG" and see what your compiler +does. + +Copyright notice:- + +(c) 1993 Christopher Sawtell. + +I assert the right to be known as the author, and owner of the +intellectual property rights of all the files in this material, +except for the quoted examples which have their individual +copyright notices. Permission is granted for onward copying, +but not modification, of this course and its use for personal +study only, provided all the copyright notices are left in the +text and are printed in full on any subsequent paper reproduction. + +-- + +----------------------------------------------------------------------+ + | NAME Christopher Sawtell | + | SMAIL 215 Ollivier's Road, Linwood, Christchurch, 8001. New Zealand.| + | EMAIL chris@gerty.equinox.gen.nz | + | PHONE +64-3-389-3200 ( gmt +13 - your discretion is requested ) | + +----------------------------------------------------------------------+ diff --git a/reference/C/CONTRIB/SAWTELL/c-lesson.6 b/reference/C/CONTRIB/SAWTELL/c-lesson.6 new file mode 100755 index 0000000..67f8852 --- /dev/null +++ b/reference/C/CONTRIB/SAWTELL/c-lesson.6 @@ -0,0 +1,331 @@ + + Lesson 5. + + The Pre-processor and Header Files. + +The pre-processor is activated by a '#' character in column one of the source +code. There are several statements vis: + +#include + +#define +#undef + +#if +#else +#endif + +#ifdef +#ifndef + +#pragma + + #include. + + In the programming examples presented in the previous lessons you will +probably have noticed that there is this statement: + +#include <stdio.h> + +right at the start of the program text. This statement tells the pre-processor +to include the named file in the your program text. As far as the compiler is +concerned this text appears just as if you had typed it yourself! + + This is one of the more useful facilities provided by the 'C' language. +The #include statement is frequently combined with the #if construct. +In this program fragment the file "true.h" is included in your program +if the pre-processor symbol FLAG is true, and "false.h" included if FLAG +is false. + +#if ( FLAG ) +# include "true.h" +#else +# include "false.h" +#endif + +This mechanism has many uses, one of which is to provide +portability between all the 57,000 slightly different versions of unix and also +other operating systems. Another use is to be able to alter the way in which +your program behaves according to the preference of the user. + +Of course, you will be asking the question "Where is the file stored?". +Well, if the filename is delimited by the "<" and ">" characters as in the +example above the file comes from the /usr/include directory, but if the name +of the file is delimited by quotes then the file is to be found in your current +working directory. (This is not quite the whole truth as 'C' compilers allow +you to extend the search path for the include files using command line option +switches. - See your compiler manual for the whole story. ) + +So, I would like to suggest that you to have a look around the /usr/include +directory and its /sys sub-directory. You should use either your editor +in 'view' mode or the pg utility. This will ensure that you can't have an +accident and alter one of the files by mistake if you are slightly silly +and just happen to be logged on as the super-user. + +A typical file to examine is usr/include/time.h. + +It's quite small so here it is. + +/* Copyright (c) 1984 AT&T */ +/* All Rights Reserved */ + +/* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T */ +/* The copyright notice above does not evidence any */ +/* actual or intended publication of such source code. */ + +#ident "@(#)/usr/include/time.h.sl 1.5 4.2 04/20/87 18195 AT&T-SF" +/* 3.0 SID # 1.2 */ +struct tm { /* see ctime(3) */ + int tm_sec; + int tm_min; + int tm_hour; + int tm_mday; + int tm_mon; + int tm_year; + int tm_wday; + int tm_yday; + int tm_isdst; +}; +extern struct tm *gmtime(), *localtime(); +extern char *ctime(), *asctime(); +int cftime(), ascftime(); +extern void tzset(); +extern long timezone, altzone; +extern int daylight; +extern char *tzname[]; + + As you can see ( forgetting about the comments and #ident ) there are three +different uses for the file. + + a) The definition of data structures and types. + b) The declaration of functions which use the data structures. + c) The declaration of of external data objects. + + These lines of code are all you need in your program in order to be able to +use, in this case, the library routine to access the clock in the computer, +but of course the paradigm applies to all programs which are created by one +programmer and used by another member of the programming team. Note that, by +proxy, or whatever, the author of the library routines has in effect become +a member of your programming team. + + You might care to write a program or two which use this header file, +and for those who are motivated it might be an idea to re-implement localtime +so that it understands Summer Time in the Southern Hemisphere. (!) + +Using another totally trivial example in order to get the idea across please +examine the hello world program printed immediately below. + +/* ------------------------------------------------------------ */ + +#ident "@(#) hw_uc.h UPPER CASE version." + +#define HELLO_MESSAGE "HELLO WORLD...\n"; + +/* ------------------------------------------------------------ */ + +#ident "@(#) Hello World" + +#include <stdio.h> +#include HW_H + +#if !defined( HELLO_MESSAGE ) +# error "You have forgotten to define the header file name." +#endif + +char *format = "%s", + *hello = HELLO_MESSAGE; + +main() +{ + printf ( format, hello ); + } + +/* ------------------------------------------------------------ */ + +You will no doubt notice that the symbol HW_H is used instead of a header file +name. This gives us the ability to force the inclusion of any file we wish by +defining the symbol HW_H to be the desired file name. It can be done like this: + +cc -DHW_H="\"hw_uc.h\"" hello.c + +The compiler output is placed, by default, in the file a.out, so to execute it +issue the command: + +a.out + +Which, fairly obviously, produces the output: + +HELLO WORLD... + +As we are going to generate another version of the program we had better move +the executable image file to another file name: + +mv a.out hello_uc + +Now to produce the other version issue the command line: + +cc -DHW_H="\"hw_lc.h\"" hello.c; mv a.out hello_lc; hello_lc + +Which compiles the other version of the hello.c program, using this version of +the include file: + +/* ------------------------------------------------------------ */ +#ident "@(#) hw_lc.h Lower Case version." + +#define HELLO_MESSAGE "Hello World...\n"; +/* ------------------------------------------------------------ */ + +and then moves the executable image to a different file and executes it. +Note that more than one command per line can be issued to the shell by +separating the commands with the ';' delimiting character. +Here - Surprise, Surprise - is the output of the second version. + +Hello World... + +I'd like to suggest that you use your editor to cut these example programs +and the shell file below out of the mail file and have a play with them. + +/* ----------------------------------------- */ + +# @(#) Shell file to do the compilations. + +cc -o hello_uc -DHW_H="\"hw_uc.h\"" hello.c +cc -o hello_lc -DHW_H="\"hw_lc.h\"" hello.c + +/* ----------------------------------------- */ + + +#define + + This statement allows you to set up macro definitions. The word immediately +after the #define, together with its arguments, is expanded in the program +text to the whole of the rest of the line. + +#define min(a, b) ((a<b) ? a : b ) + + Some things to note: + + 1) There isn't a space between the last character of the symbol being defined + and the opening parenthesis enclosing the arguments, and there MUST NOT BE + one. + + 2) The code into which the macro is expanded MUST always be enclosed in + parentheses and for safety always use parentheses to get the arithmetic + right. + + 3) Never EVER define a macro, and use it with a side effect. e.g. + + c = min ( a++, b); /* DON'T _EVER_ DO THIS!!! */ + + Do you think that the value of 'a' will get advanced after the + macro is used? Well it WON'T. It gets incremented after the less + than test and before the values get assigned! I have written a tiny + program which uses the min macro above. Have a look at the output + from the pre-processor. Lesson One told you how to do this. + Now execute it and get an educative surprise! + +/* ----------------------------------------- */ + +#include <stdio.h> +#define min(a, b) ((a<b) ? a : b ) + +main() +{ int a,b,c; + + a = 1; + b = 2; + c = min ( a++, b); /* DON'T _EVER_ DO THIS!!! */ + printf ( "a: %d, b: %d, c: %d\n", a, b, c ); + } + +/* ----------------------------------------- */ + + 4) You can continue a macro on the next line by putting a \ ( back-slash ) + as THE VERY LAST character on the line. NOTHING, not even a space may + follow, as your compiler just can't handle it. I spent far too long trying + to find one of those really difficult bugs, and it turned out that this + was the problem - spaces are transparent aren't they? + + 5) Using macros is fast and convenient, but they do take up a lot of memory + because the code is expanded and inserted into the output stream for + every occurrence of the macro in your code. There is a trade-off between + using a macro and a function. + + The symbol does not have to be the handle for a macro expansion, but can just +be equated to a single constant. This is done many times over in the header +files provided by the operating system vendor. Have a look in +/usr/include/sys/file.h for an example of this. + +#undef + + Not surprisingly this preprocessor command removes a symbol WHICH IS BEING + USED BY THE PRE-PROCESSOR - don't confuse it with compiler proper symbols. + + Note that the symbol can be a macro name, in which case the space + used for the code expansion is made available for re-use. + +#if ( FLAG ) + + /* Code in here is sent on to the compiler if FLAG is true. */ + +#else + + /* Code in here is sent on to the compiler if FLAG is false. */ + +#endif + + When the pre-processor encounters one of these, the lines of code between the +#if and the corresponding #else or #endif are either skipped over or allowed to +proceed to the compilation phase depending on the truth or falsity of the +logical expression ( FLAG ). All the logical and boolean expressions available +as part of the 'C' language are available here. You are also allowed to say: + +#if defined( FLAG ) or, +#if !defined( FLAG ) + + + The symbol FLAG may be an expression which reduces to a boolean value. + + A convention which is adhered to quite well is that all pre-processor +symbols are in UPPER_CASE so as to make them obvious. + +#ifdef FLAG or, +#ifndef FLAG + + These two statements are the old fashioned way of testing whether a symbol is +defined or not. They are absolutely the same as the previous example. + + There are two more pre-processor statements, namely the #pragma and +the "stringizing" operator. The #pragma is used to alter the way in which +the compiler works on a block of code, but it is completely implementation +dependant and you must refer to your compiler manual. I can't help as +they are all different. The "stringizing" operator is quite an advanced +technique and will be dealt with later on. + +Copyright notice:- + +(c) 1993 Christopher Sawtell. + +I assert the right to be known as the author, and owner of the +intellectual property rights of all the files in this material, +except for the quoted examples which have their individual +copyright notices. Permission is granted for onward copying, +but not modification, of this course and its use for personal +study only, provided all the copyright notices are left in the +text and are printed in full on any subsequent paper reproduction. + +-- + +----------------------------------------------------------------------+ + | NAME Christopher Sawtell | + | SMAIL 215 Ollivier's Road, Linwood, Christchurch, 8001. New Zealand.| + | EMAIL chris@gerty.equinox.gen.nz | + | PHONE +64-3-389-3200 ( gmt +13 - your discretion is requested ) | + +----------------------------------------------------------------------+ + +-- + +----------------------------------------------------------------------+ + | NAME Christopher Sawtell | + | SMAIL 215 Ollivier's Road, Linwood, Christchurch, 8001. New Zealand.| + | EMAIL chris@gerty.equinox.gen.nz | + | PHONE +64-3-389-3200 ( gmt +13 - your discretion is requested ) | + +----------------------------------------------------------------------+ diff --git a/reference/C/CONTRIB/SAWTELL/c-lesson.7 b/reference/C/CONTRIB/SAWTELL/c-lesson.7 new file mode 100755 index 0000000..d5caba1 --- /dev/null +++ b/reference/C/CONTRIB/SAWTELL/c-lesson.7 @@ -0,0 +1,161 @@ + +Lesson 6 + + Libraries, why we have them, and how to make and use them. + + In order to simplify the creation of programs for its customers, +software vendors make available one or more libraries of functions +which have general application. + + When you write a program in 'C' much, if not most, of the "hard work" +is done by explicitly called functions, which you call by simply writing +their names in your program script. Unfortunately there is a little bit +more to it than that. If the function returns a value which is other +than of type int, you have to tell the compiler the type of the returned +value. An example will, I hope make things clear. + + Lets's suppose that you have been given the task of, making things +stupidly simplistic for a book example, sorting a list of names into +alphabetical order. ( Yes, I do know this can, and should be done in just +one line of shell script! However that's another story for another day. ) + + You look diligently through the Programmer Reference Manual, discover +that the prose is almost opaque, and find a couple of interesting looking +routines called strcmp, and qsort. You decide to use these library +functions. Now for just a moment lets consider the ins and outs of what, +in effect, you have just done. You have just asked a member of the team +of programmers who created the library to join you, by proxy as it were, in +creating your masterpiece. A useful concept, which has been in use +almost since the start of electronic computing. + + To re-focus the mind on the task at hand; let's look in the Reference +Manual +at the page for qsort(3C) - The 3C in parenthesis is the cryptic code which +is the unix apology for a reference to section 3C in the Manual! So find +section 3C and look up qsort. Now have a look at the SYNOPSIS, and notice +that there is no mention of a header file to #include, and also notice that +qsort returns a void, not an int. This means that there is no header file +/usr/include/qsort.h ( for my version of unix - system V Release 3.2.2 - +anyway ) and you have to declare qsort yourself as an external function. +Also turn to the page string(3C) in the fine manual. Notice that the +SYNOPSIS here includes the line #include <string.h> so you have to put +it in your program text. Once more an example to make it all clear. + + +/* ----------------------------------------- */ + +#ident "@(#) qsort-demo.c" + +#include <stdio.h> +#include <string.h> +#include <assert.h> + +extern void qsort (); +extern int strcmp(); /* Some compilers need this defined, most don't. */ + +char names[22][25] = /* Here are some names to sort. */ +{ + "John Nagle", "Colin Douthwaite", "Ian Lance Taylor", "Brian J. Murrell", + "Pete", "Geoff Mccaughan", "David Liebert", "Operator", "Bill Baucum", + "Victor Volkman", "Chay R Harley", "Dan Romanchik", "Larry Kollar", + "Gaston Ormazabal", "Arijit Chandra", "Kenneth Mark Hopkinson", + "Kerr Hatrick", "Tim Love", "Robert M. Juranitch", "Jeffrey Micke", + "Duong Quoc", "Jagadesh Vasudevamurthy" + }; + +#define NUMBER_OF_NAMES sizeof ( names ) / sizeof ( names[0] ) + +main() +{ + int i; + + /* + ** Print the unsorted names. + */ + + printf ( "The Unsorted Names.\n" ); + for ( i = 0; i < NUMBER_OF_NAMES; i++ ) printf ( "%s\n", names[i] ); + + /* + ** Print a prompt, and wait. + */ + + printf ( "Press RETURN to continue: " ); + fflush ( stdout ); + getchar(); + + /* + ** Now apply qsort to the arrary of character strings. + */ + + qsort (( char * ) names, NUMBER_OF_NAMES, sizeof ( *names ), strcmp ); + + assert ( names[0][0] < names[1][0] ); /* Quick check to see it's done +it. */ + + /* + ** Print the sorted names. + */ + + printf ( "The Sorted Names.\n" ); + for ( i = 0; i < NUMBER_OF_NAMES; i++ ) printf ( "%s\n", names[i] ); + } + +/* ----------------------------------------- */ + + Note very well:- + + I wanted 22 short character strings for the data items +for the demo to sort. So grep, uniq, cut, tail, and finally a tiny bit of +vi fished eminently suitable strings out of "mail.received". If your name +is not on the list, well I'm sorry, but the world is not a fair place! + + So that's how you use library routines. I chose qsort because it is +simple to use, and shows off a feature of 'C' well, that's the ability +to use a name of a function as a pointer and then execute that function +from within the called function. It's strcmp in this case. A quick look +at the compiler output is instructive. + + As is the nature of the animal, a tin-pot little program, which should +have taken all of ten minutes to get going in fact took more like two +hours. I put it down to the fact that the Fine Manual did not make it +adequately obvious that the data array acted on by qsort was the data itself. +From reading the Fine Manual I got the impression that the array acted on +was an array of pointers. You live and learn. It would be a much faster +qsort if, in fact, the sorting function sorted pointers to data instead of +the data itself. You might like to make a function qsort_p which worked in +in this way. The qsort algorithm is well documented elsewhere. + + There is just one more point to notice about using function libraries. +The 'C' compilation system will load functions from the library /lib/libc.a +as a default. All others have to be indicated to the linking loader by a +switch on the shell interactive command line. + +$ cc -o prog prog.c -L /usr/local/lib -lgdbm -lmalloc + + You might use this command line to compile and link a program which +uses both the GNU gdbm data-base manager library, which is installed in +the directory /usr/local/lib, and the enhanced malloc library. Now, there +hangs a tale! I remember having to compile a program suit off Usenet and +it just would not work properly. No error messages, no warnings, no +missing linking-loader symbols. It just "died" when I tried to run it. +After many, many hours of total frustration, I thought that I would try +linking in the enhanced malloc library. Presto! It worked. + + Note very well. + + A common misconception is the notion that having a #include <whatever.h> +line in the source text will automagically tell the linking loader to +get the functions from the appropriate library. Remove this erroroneous +notion from your mind. It won't. The -lwhatever flag on the shell command +line which initiates execution of "cc" or "ld" is the only way to tell the +loader where to look for the required library. + + +-- + +----------------------------------------------------------------------+ + | NAME Christopher Sawtell | + | SMAIL 215 Ollivier's Road, Linwood, Christchurch, 8001. New Zealand.| + | EMAIL chris@gerty.equinox.gen.nz | + | PHONE +64-3-389-3200 ( gmt +13 - your discretion is requested ) | + +----------------------------------------------------------------------+ diff --git a/reference/C/CONTRIB/SAWTELL/c-lesson.8 b/reference/C/CONTRIB/SAWTELL/c-lesson.8 new file mode 100755 index 0000000..8e2bff9 --- /dev/null +++ b/reference/C/CONTRIB/SAWTELL/c-lesson.8 @@ -0,0 +1,502 @@ + + Lesson 7. + + De-bugging Strategies. + + >>>>>>>> Proper Preparation Prevents Piss-Poor Performance. <<<<<<<< + + This lesson is really a essay about how to go about writing programs. + + I know that by far the best way to greatly reduce the amount of effort +required to get a program going properly is to avoid making mistakes in the +first palace! Now this might seem to be stating the absolute obvious, and it +is but after looking at many programs it would seem that there is a very +definite need to say it. + + So how does one go about reducing the probability of making mistakes? + + There are many strategies, and over the years I have evolved my own set. + I have found that some of the most important are: + + 1) Document what you are going to do before yes BEFORE you write any code. + Set up the source files for the section of the program you are going to + write and put some lines of explanation as to what you intend to do in + this file. Be as precise as you can, but don't go into the detail of + explaining in English, or your First Language, exactly what every + statement does. + + 2) Make sure that you keep each file as small as is sensible. Some program + authors say that one should put only one function in a file. It's my + personal opinion that this is going a little bit over the top, but + certainly you should not have more than one logical activity in a source + file. It's easier to find a needle in a tiny haystack than in a big one! + + 3) Always use names for the objects in your program which are fully + descriptive, or at the very least are meaningful nmemonics. Put yourself + in the position of some poor soul who - a couple of years later, after you + have long finished with the project, and left the country - has been given + the task of adding a small feature to your exquisite program. Now in the + rush to get your masterpiece finished you decided to use variable names + like "a4" and "isb51" simply so that you can get the line typed a + fraction of a second faster than if you used something like + "customer_address[POST_CODE]" and "input_status_block[LOW_FUEL_TANK_#3]. + The difference in ease of understanding is obvious, isn't it? However + judging by some programs which I have seen published in both magazines and + in the public domain program sources, the point has still to be made. + + 4) ALWAYS take great care with the layout of your code. + It's my opinion that the opening brace of ALL program structures should + be on a new line. Also if you put them in the leftmost column for structs, + enums, and initialised tables, as well as functions, then the + 'find function' keystrokes ( "[[" and "]]" ) in vi will find them as well + as the functions themselves. Make sure you have the "showmatch" facility + in vi turned on. ( And watch the cursor jump when you enter the + right hand brace, bracket, or parenthesis. ) + + 5) Try as hard as you can to have as few global variables as possible. + Some people say never have any globals. This is perhaps a bit too + severe but global variables are a clearly documented source of + programming errors. If it's impossible to perform a logical activity + in an efficient way without having a global or two, then confine + the scope of the globals to just the one file by marking the defining + declaration "static". This stops the compiler producing a symbol which + the linking loader will make available to all the files in your source. + + 6) Never EVER put 'magic numbers' in you source code. Always define constants + in a header file with #define lines or enum statements. + + Here is an example:- + + +/* ----------------------------------------- */ + +#include <stdio.h> + +enum status_input_names +{ + radiator_temperature, + oil_temperature, + fuel_pressure, + energy_output, + revolutions_per_minute + }; + +char *stats[] = +{ + "radiator_temperature", + "oil_temperature", + "fuel_pressure", + "energy_output", + "revolutions_per_minute" + }; + +#define NUMBER_OF_INPUTS ( sizeof ( stats ) / sizeof ( stats[0])) + +main() +{ + enum status_input_names name; + + printf ( "Number of Inputs is: %d\n", NUMBER_OF_INPUTS ); + for ( name = radiator_temperature; name < NUMBER_OF_INPUTS; name++) + { + printf ( "\n%s", stats[ name ] ); + } + printf ( "\n\n" ); + } + +/* ----------------------------------------- */ + + Note that as a side effect we have available the meaningful symbols + radiator_temperature etc. as indices into the array of status input names + and the symbol NUMBER_OF_INPUTS available for use as a terminator in the + 'for' loop. This is quite legal because sizeof is a pseudo-function and the + value is evaluated at the time of compilation and not when the program is + executed. This means that the result of the division in the macro is + calculated at the time of compilation and this result is used as a literal + in the 'for' loop. No division takes place each time the loop is executed. + + To illustrate the point I would like to tell you a little story which is + fictitious, but which has a ring of truth about it. + Your employer has just landed what seems to be a lucrative contract with + an inventor of a completely new type of engine. We are assured that after + initial proving trials one of the larger Japanese motor manufactures is + going to come across with umpteen millions to complete the development of + the design. You are told to write a program which has to be a simple and + straightforward exercise in order to do the job as cheaply as possible. + Now, the customer - a some-what impulsive type - realises that his + engine is not being monitored closely enough when it starts to rapidly + dis-assemble itself under high speed and heavy load. You have to add a + few extra parameters to the monitoring program by yesterday morning! + You just add the extra parameters into the enumand the array of pointers + to the character strings. So: + +enum status_input_names +{ radiator_temperature, + radiator_pressure, + fuel_temperature, + fuel_pressure, + oil_temperature, + oil_pressure, + exhaust_manifold_temperature + }; + + Let's continue the story about the Japanese purchase. Mr. Honda ( jun ) has + come across with the money and the result is that you are now a team leader + in the software section of Honda Software ( YourCountry ) Ltd. The project of + which you are now leader is to completely rewrite your monitoring program and + add a whole lot of extra channels as well as to make the printouts much more + readable so that your cheap, cheerful, and aesthetic-free program can be sold + as the "Ultimate Engine Monitoring Package" from the now world famous Honda + Real-time Software Systems. You set to work, Honda et. al. imagine that there + is going to be a complete redesign of the software at a cost of many million + Yen. You being an ingenious type have written the code so that it is easy to + enhance. + + The new features required are that the printouts have to be printed with the + units of measure appended to the values which have to scaled and processed so + that the number printed is a real physical value instead of the previous + arrangement where the raw transducer output was just dumped onto a screen. + + What do you have to do? + + Thinking along the line of "Get the Data arranged correctly first". + You take you old code and expand it so that all the items of information + required for each channel are collected into a struct. + +enum status_input_names +{ + radiator_temperature, + radiator_pressure, + fuel_temperature, + fuel_pressure, + oil_temperature, + oil_pressure, + exhaust_manifold_temperature, + power_output, + torque + }; + +typedef struct channel +{ + char *name; /* Channel Name to be displayed on screen. */ + int nx; /* position of name on screen x co-ordinate. +*/ + int ny; /* ditto for y */ + int unit_of_measure; /* index into units of measure array */ + char value; /* raw datum value from 8 bit ADC */ + char lower_limit; /* For alarms. */ + char upper_limit; + float processed_value; /* The number to go on screen. */ + float offset; + float scale_factor; + int vx; /* Position of value on screen. */ + int vy; + }CHANNEL; + +enum units_of_measure { kPa, degC, kW, rpm, Volts, Amps, Newtons }; + +char *units { "kPa", "degC", "kW", "rpm", "Volts", "Amps", "Newtons" }; + +CHANNEL data [] = +{ + { "radiator temperature", + { "radiator pressure", + { "fuel temperature", + { "fuel pressure", + { "oil temperature", + { "oil pressure", + { "exhaust manifold temperature", + { "power output", + { "torque", + }; + +#define NUMBER_OF_INPUTS sizeof (data ) / sizeof ( data[0] ) + +Now the lesson preparation is to find the single little bug in the above +program fragment, to finish the initialisation of the data array of type +CHANNEL and to have a bit of a crack at creating a screen layout +program to display its contents. Hint: Use printf(); +( Leave all the values which originate from the real world as zero. ) + + + Here are some more tips for young players. + + 1) Don't get confused between the logical equality operator, + + == + + and the assignment to a variable operator. + + = + + This is probably the most frequent mistake made by 'C' beginners, and + has the great disadvantage that, under most circumstances, the compiler + will quite happily accept your mistake. + + 2) Make sure that you are aware of the difference between the logical + and bit operators. + + && This is the logical AND function. + || This is the logical OR function. + The result is ALWAYS either a 0 or a 1. + + & This is the bitwise AND function used for masks etc. + The result is expressed in all the bits of the word. + + 3) Similarly to 2 be aware of the difference between the logical + complementation and the bitwise one's complement operators. + + ! This is the logical NOT operator. + ~ This is the bitwise ones complement op. + + Some further explanation is required. In deference to machine efficiency a + LOGICAL variable is said to be true when it is non-zero. So let's set a + variable to be TRUE. + + 00000000000000000000000000000001 A word representing TRUE. + Now let's do a logical NOT !. + 00000000000000000000000000000000 There is a all zero word, a FALSE. + + 00000000000000000000000000000001 That word again. TRUE. + Now for a bitwise complement ~. + 11111111111111111111111111111110 Now look we've got a word which is + non-zero, still TRUE. + + Is this what you intended? + + 4) It is very easy to fall into the hole of getting the + '{' & '}'; '[' & ']'; '(' & ')'; symbol pairs all messed up and the + computer thinks that the block structure is quite different from that + which you intend. Make sure that you use an editor which tells you the + matching symbol. The UNIX editor vi does this provided that you turn + on the option. Also take great care with your layout so that the block + structure is absolutely obvious, and whatever style you choose do take + care to stick by it throughout the whole of the project. + A personal layout paradigm is like this: + + Example 1. + +function_type function_name ( a, b ) +type a; +type b; +{ + type variable_one, variable_two; + + if ( logical_expression ) + { + variable_one = A_DEFINED_CONSTANT; + if ( !return_value = some_function_or_other ( a, + variable_one, + &variable_two + ) + ) + { + error ( "function_name" ); + exit ( FAILURE ); + } + else + { + return ( return_value + variable_two ); + } + } /* End of "if ( logical_expression )" block */ + } /* End of function */ + + This layout is easy to do using vi with this initialisation script + in either the environment variable EXINIT or the file ${HOME}/.exrc:- + +set showmode autoindent autowrite tabstop=2 shiftwidth=2 showmatch wm=1 + + Example 2. + +void printUandG() +{ + char *format = +"\n\ + User is: %s\n\ + Group is: %s\n\n\ + Effective User is: %s\n\ +Effective Group is: %s\n\n"; + + ( void ) fprintf ( tty, + format, + passwd_p->pw_name, + group_p->gr_name, + epasswd_p->pw_name, + egroup_p->gr_name + ); + } + + Notice how it is possible to split up format statements with a '\' as + the last character on the line, and that it is convenient to arrange + for a nice output format without having to count the + field widths. Note however that when using this technique that the '\' + character MUST be the VERY LAST one on the line. Not even a space may + follow it! + + In summary I *ALWAYS* put the opening brace on a new line, set the tabs + so that the indentation is just two spaces, ( use more and you very quickly + run out of "line", especially on an eighty column screen ). If a statement + is too long to fit on a line I break the line up with the arguments set out + one to a line and I then the indentation rule to the parentheses "()" + as well. Sample immediately above. Probably as a hang-over from a particular + pretty printing program which reset the indentation position after the + printing of the closing brace "}", I am in the habit of doing it as well. + Long "if" and "for" statements get broken up in the same way. This is + an example of it all. The fragment of code is taken from a curses oriented + data input function. + + /* + ** Put all the cursor positions to zero. + */ + + for ( i = 0; + s[i].element_name != ( char *) NULL && + s[i].element_value != ( char *) NULL; + i = ( s[i].dependent_function == NULL ) + ? s[i].next : s[i].dependent_next + ) + { /* Note that it is the brace and NOT the */ + /* "for" which moves the indentation level. */ + s[i].cursor_position = 0; + } + + /* + ** Go to start of list and hop over any constants. + */ + + for ( i = edit_mode = current_element = 0; + s[i].element_value == ( char *) NULL ; + current_element = i = s[i].next + ) continue; /* Note EMPTY statement. */ + + /* + ** Loop through the elements, stopping at end of table marker, + ** which is an element with neither a pointer to an element_name nor + ** one to a element_value. + */ + + while ( s[i].element_name != ( char *) NULL && + s[i].element_value != ( char *) NULL + ) + { + int c; /* Varable which holds the character from the keyboard. */ + + /* + ** Et Cetera for many lines. + */ + + } + + Note the commenting style. The lefthand comments provide a general +overview of what is happening and the righthand ones a more detailed view. +The double stars make a good marker so it is easy to separate the code and +the comments at a glance. + + The null statement. + + You should be aware that the ";" on its own is translated by the compiler +as a no-operation statement. The usefullness of this is that you can do +little things, such as counting up a list of objects, or positioning a pointer +entirely within a "for" or "while" statement. ( See example above ). +There is, as always, a flip side. It is HORRIBLY EASY to put a ";" at the +end of the line after the closing right parenthesis - after all you do just +that for function calls! The suggestion is to both mark deliberate null +statements with a comment and to use the statement "continue;". Using +the assert macro will pick up these errors at run time. + + The assert macro. + + Refer to the Programmers Reference Manual section 3X and find the +documentation on this most useful tool. + + As usual an example is by far the best wasy to explain it. + +/* ----------------------------------------- */ + +#ident "@(#) assert-demo.c" + +#include <stdio.h> +#include <assert.h> + +#define TOP_ROW 10 +#define TOP_COL 10 + +main() +{ + int row, col; + + for ( row = 1; row <= TOP_ROW; row++); + { + assert ( row <= TOP_ROW ); + for ( col = 1; col <= TOP_COL; col++ ) + { + assert ( col <= TOP_COL ); + printf ( "%4d", row * col ); + } + printf ( "\n" ); + } + } + +/* ----------------------------------------- */ + + Which produces the output:- + +Assertion failed: row <= TOP_ROW , file assert-demo.c, line 15 +ABORT instruction (core dumped) + + It does this because the varable "row" is incremented +to one greater than The value of TOP_ROW. + + Note two things: + + 1) The sense of the logical condition. The assert is asserted + as soon as the result of the logical condition is FALSE. + Have a look at the file /usr/include/assert. + Where is the ";" being used as an empty program statement? + + 2) The unix operating system has dumped out an image of the executing + program for examination using a symbolic debugger. Have a play with + "sdb" in preparation for the lesson which deals with it in more + detail. + + Lets remove the errant semi-colon, re-compile and re-run the program. + + 1 2 3 4 5 6 7 8 9 10 + 2 4 6 8 10 12 14 16 18 20 + 3 6 9 12 15 18 21 24 27 30 + 4 8 12 16 20 24 28 32 36 40 + 5 10 15 20 25 30 35 40 45 50 + 6 12 18 24 30 36 42 48 54 60 + 7 14 21 28 35 42 49 56 63 70 + 8 16 24 32 40 48 56 64 72 80 + 9 18 27 36 45 54 63 72 81 90 + 10 20 30 40 50 60 70 80 90 100 + + Here's the ten times multiplication table, for you to give to to +the nearest primary-school child! + + I would agree that it is not possible to compare the value of a program +layout with a real work of fine art such as a John Constable painting or +a Michaelangelo statue, I do think a well laid out and literate example of +programming is not only much easier to read and understand, but also it +does have a certain aesthetic appeal. + +Copyright notice:- + +(c) 1993 Christopher Sawtell. + +I assert the right to be known as the author, and owner of the +intellectual property rights of all the files in this material, +except for the quoted examples which have their individual +copyright notices. Permission is granted for onward copying, +but not modification, of this course and its use for personal +study only, provided all the copyright notices are left in the +text and are printed in full on any subsequent paper reproduction. + +-- + +----------------------------------------------------------------------+ + | NAME Christopher Sawtell | + | SMAIL 215 Ollivier's Road, Linwood, Christchurch, 8001. New Zealand.| + | EMAIL chris@gerty.equinox.gen.nz | + | PHONE +64-3-389-3200 ( gmt +13 - your discretion is requested ) | + +----------------------------------------------------------------------+ diff --git a/reference/C/CONTRIB/SAWTELL/c-lesson.9 b/reference/C/CONTRIB/SAWTELL/c-lesson.9 new file mode 100755 index 0000000..5d03e3b --- /dev/null +++ b/reference/C/CONTRIB/SAWTELL/c-lesson.9 @@ -0,0 +1,433 @@ + + Lesson 8. + + This lesson and the following one will examine how to use the program +structure - as opposed to data structure - reserved words. + + Lets start with the looping structures: + + do repeated_statement while ( logical_expression ); + + repeated_statement, which may be a block of code, will be executed +repetitively until the logical_expression, becomes false. If you have been +exposed to ( corrupted by? ) another language remember that there is no +`until' test at the end of a loop. Note that the repeated_statement is always +executed once irrespective of the state of the logical_expression. + + while ( logical_expression ) repeated_statement; + + repeated_statement is executed repetitively while the logical_expression +is true. Once again statement may be a block of code. Note that if the +logical_expression evaluates to FALSE then the repeated_statement is NEVER +executed. + + Associated with the looping structures are the control words: + + break; + continue; + + break; allows you to leave a loop in the middle of a block, and + continue; allows you to re-start it from the top. + + Finally we must not forget the most common and useful looping construct: + + for ( initialising statement; logical_expression; incremental_statement ) + repeated_statement; + + Some further explanation is needed. The initialising statement is +executed once, but to allow for the need to initialise several separate +variables the assignment statements may be separated by commas. The +logical_expression must be true for the loop to run, and the +incremental_statement is executed once each time the loop is run. +The for statement is completely general and may, for example, be used to +manipulate a set of pointers to operate on a linked list. + +Some examples. + + A do loop program. + +#ident "@(#) do_demo.c - An example of the do loop" + +#include <stdio.h> + +main() +{ + char character; + + character = 'a'; + + do printf ( "%c", character ); while ( character++ < 'z' ); + printf ( "\n" ); + } + + Fairly obviously it prints: + +abcdefghijklmnopqrstuvwxyz + + A while loop example. + +#ident "@(#) while_demo.c - An example of the while loop" + +#include <stdio.h> + +main() +{ + char character; + + character = 'a'; + + while ( character <= 'z' ) printf ( "%c", character++ ); + printf ( "\n" ); + } + + Its output is exactly the same as the previous example: + +abcdefghijklmnopqrstuvwxyz + + In this totally trivial case it is irrelevant which program structure + you use, however you should note that in the `do' program structure the + repeated statement is always executed at least once. + A for loop example. + + The `for' looping structure. + +#ident "@(#) for_demo.c - An example of the for loop" + +#include <stdio.h> + +main() +{ + char character; + + for ( character = 'a'; character <= 'z' ; character++ ) + { + printf ( "%c", character ); + } + printf ( "\n" ); + } + + Surprise, Surprise! + +abcdefghijklmnopqrstuvwxyz + + You should be aware that in all the looping program structures, the +repeated statement can be a null statement ( either just a `;' or the +reserved word `continue;' ). This means that it is possible to - for +example - position a pointer, or count up some items of something or other. +It isn't particularly easy to think up a trivial little program which +demonstrates this concept, however the two `for' loops give some indication +of the idea. + +#ident "@(#) pointer_demo.c - Pointer operations with the for loop" + +#include <stdio.h> + +main() +{ + char character, *character_pointer, alphabets [ 53 ]; + + for ( character = 'a', character_pointer = alphabets; /* Start conditions */ + character <= 'z'; /* Run while true */ + *character_pointer++ = character++ /* All the work */ + )TRUE continue; + + for ( character = 'A'; /* character_pointer is at the right place already */ + character <= 'Z'; + *character_pointer++ = character++ + ) continue; + + *character_pointer = (char) '\000'; /* NULL character to terminate string. */ + + printf ( "%s\n\n", alphabets ); + } + + Another Surprise! + +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ + + So much for the looping structures provided by the `C' language. The +other main structures required to program a computer are the ones which +alter the program flow. These are the switch, and the if and its extension +the if ... else combination. More demo programs are much the best way of +getting the message across to you, so here they are, first the if construct. + +#ident "if_demo.c" + +#include <stdio.h> + +main(argc, argv) +int argc; +char **argv; +{ + if ( argc > 1 ) printf ( "You have initiated execution with arguments."}; + } + + And the if ... else demo. + +#ident "if_else_demo.c" +/* +** The Language #define could go in the compiler invocation line if desired. +*/ + +#define ENGLISH + +#include <stdio.h> + +/* +** The message and text fragments output by the program. +*/ + +char *messages[] = +{ +#if defined( ENGLISH ) +#ident "@(#)ENGLISH Version" + "\nUsage: if_else_demo <numeric argument 1> <numeric argument 2>\n\n", + "The first argument is ", + "the second", + "equal to ", + "bigger than ", + "smaller than " +#endif + +#if defined( FRANCAIS ) +#ident "@(#)FRENCH Version" + + put the French translation in here so that we are ready to export to + French speaking Countries. I'd be grateful if a French speaker could + make the translation for me. + +#endif + }; + +/* +** Meaningful words defined to constants +*/ + +#define USAGE 0 +#define FIRST 1 +#define SECOND 2 +#define EQUAL 3 +#define BIGGER 4 +#define SMALLER 5 + +#define SUCCESS 0 +#define FAILURE 1 + +/* +** We need this more than once so it can be put in a function. +*/ + +void usage() +{ + printf ( messages[USAGE]); + exit ( FAILURE ); + } + +/* +** Main program function starts here. ( At the top of a page no less! ) +*/ + +int main ( argc, argv ) +int argc; +char **argv; +{ + int message_index; + double i, j, strtod(); + char *ptr; + + if ( argc != 3 ) usage(); /* have we been given the right */ + /* number of arguments. */ + i = strtod ( argv[1], &ptr); /* Convert to a double float. */ + if ( ptr == argv[1] ) usage(); /* Successful conversion? */ + j = strtod ( argv[2], &ptr); /* Convert to a double float. */ + if ( ptr == argv[2] ) usage(); /* Successful conversion? */ + +/* +** This statement uses the "ternary conditional assignment" language +** construction to assign the value required to the message indexing variable. +** Note that this concept is efficient in both the generation of machine code +** output ( compile the program with a -S switch and have a look ) and in the +** ease with which it can be understood. The assignment is obvious instead of +** being buried under a litter of `if' and `else' keywords. +*/ + + message_index = ( i == j ) ? EQUAL : ( i > j ) ? BIGGER : SMALLER; + +/* +** Now print the message. +*/ + + (void) printf ( "\n%s%s%s\n\n", /* Format string specifying 3 strings. */ + messages[ FIRST ], /* Address of string. */ + messages[ message_index ], /* ditto. */ + messages[ SECOND ] /* ditto. */ + ); + return ( SUCCESS ); + } + + Well as you can no doubt gather it simply compares two numbers on the +command line and ejects a little message depending on the relative magnitude +of the numbers. In the UNIX tradition the help message is perhaps somewhat +terse, but it serves the purpose of getting you - the student - to think +about the importance of creating programs which always cope with nonsensical +input in a civilised way. Here are the lines of output. + +Usage: if_else_demo <numeric argument 1> <numeric argument 2> + +The first argument is equal to the second + +The first argument is smaller than the second + +The first argument is bigger than the second + + Now that the international community is shrinking with vastly improved +telecommunications, it is perhaps a good idea to think carefully about +creating programs which can talk in many languages to the users. The method +of choice is - I believe - that presented above. The #if defined( LANGUAGE ) +gives us an easy method of changing the source code to suit the new sales +area. Another possibility is to put all the text output needed from a program +into a file. The file would have to have a defined layout and some consistent +way of `getting at' the message strings. + + From a commercial point of view this may or may not be a good business plan. +Quite definitely it is an absolute no no to scatter a mass of string literals +containing the messages and message fragments all over your program script. + + There are two more methods of altering the program flow. + + 1 ) The goto a label. + 2 ) The setjump / longjmp library routines. + + The concept of the go to a label construction has had reams of literary +verbiage written about it and this author does not intend to add to the pile. +Suffice it to say that a goto is a necessary language construct. There are a +few situations which require the language to have ( in practice ) some form of +unconditional jump. Treat this statement with great caution if you wish your +code to be readable by others. An example of legitimate use. + + for ( a = 0; a < MATRIX_SIZE; a++ ) + { + for ( b = 0; b < MATRIX_SIZE; b++ ) + { + if ( process ( matrix, a, b )) goto bad_matrix; + } + } + return ( OK ); + +bad_matrix: + + perror ( progname, "The data in the matrix seems to have been corrupted" ); + return ( BAD ); + + This is one of the very few "legitimate" uses of goto, as there is no +"break_to_outer_loop" in `C'. Note that some compilers complain if the label +is not immediately followed by a statement. If your compiler is one of these +naughty ones, you can put either a `;' or a pair of braces `{}' after the +`:' as a null statement. + + An example of a program package which makes extensive use of the goto is the +rz and sz modem communications protocol implementation by Chuck Forsberg of +Omen Technology. You should download it and study the code, but do remember +that the proof of the pudding argument must apply as the rz & sz system has +become extremely popular in its application because it works so well. + + The other method of changing program flow is the setjump and longjmp pair of +library functions. The idea is to provide a method of recovery from errors +which might be detected anywhere within a large program - perhaps a compiler, +interpreter or large data acquisition system. Here is the trivial example: + +#ident "set_jmp_demo.c" + +#include <stdio.h> +#include <setjmp.h> + +jmp_buf save; + +main() +{ + char c; + + for ( ;; ) /* This is how you set up a continuous loop. +*/ + { + switch ( setjmp( save )) + { +case 0: + printf ( "We get a zero returned from setjmp on setup.\n\n"); + break; /* This is the result from setting up. */ + +case 1: + printf ( "NORMAL PROGRAM OPERATION\n\n" ); + break; + +case 2: + printf ( "WARNING\n\n" ); + break; + +case 3: + printf ( "FATAL ERROR PROGRAM TERMINATED\n\nReally Terminate? y/n: " ); + fflush ( stdout ); + scanf ( "%1s", &c ); + c = tolower ( c ); + if ( c == 'y' ) return ( 1 ); + printf ( "\n" ); + break; + +default: + printf ( "Should never return here.\n" ); + break; + } + process (); + } + } + +process () +{ + int i; + + printf ( "Input a number to simulate an error condition: " ); + fflush ( stdout ); + scanf ( "%d", &i ); + i %= 3; + i++; /* So that we call longjmp with 0 < i < 4 */ + longjmp ( save, i); + } + + Although in this silly little demo the call to longjmp is in the same file +as the call to setjmp, this does not have to be the case, and in the practical +situation the call to longjmp will be a long way from the call to setjmp. The +mechanism is that setjmp saves the entire state of the computer's CPU in a +buffer declared in the jmp_buf save; statement and longjmp restores it exactly +with the exception of the register which carries the return value from longjmp. +This value is the same as the second argument in the longjmp call - i in our +little demo. This means, of course, that the stack and frame pointer registers +are reset to the old values and all the local variables being used at the time +of the longjmp call are going to be lost forever. One consequence of this is +that any pointer to memory allocated from the heap will also be lost, and +you will be unable to access the data stored in the buffer. This is what the +jargonauts call "memory leakage", and is really very difficult bug to find. +Your program runs out of dynamic memory long before it should. Take care. +So you have to keep a record of the buffers' addresses and free them +before the call to longjmp. + +More details later on when we learn about the heap memory allocation routines. + +Copyright notice:- + +(c) 1993 Christopher Sawtell. + +I assert the right to be known as the author, and owner of the +intellectual property rights of all the files in this material, +except for the quoted examples which have their individual +copyright notices. Permission is granted for onward copying, +but not modification, of this course and its use for personal +study only, provided all the copyright notices are left in the +text and are printed in full on any subsequent paper reproduction. + +-- + +----------------------------------------------------------------------+ + | NAME Christopher Sawtell | + | SMAIL 215 Ollivier's Road, Linwood, Christchurch, 8001. New Zealand.| + | EMAIL chris@gerty.equinox.gen.nz | + | PHONE +64-3-389-3200 ( gmt +13 - your discretion is requested ) | + +----------------------------------------------------------------------+ diff --git a/reference/C/CONTRIB/SAWTELL/intro.html b/reference/C/CONTRIB/SAWTELL/intro.html new file mode 100644 index 0000000..3278d20 --- /dev/null +++ b/reference/C/CONTRIB/SAWTELL/intro.html @@ -0,0 +1,24 @@ +<title>C Lesson by Chris Sawtell</title> +<h1>C Lesson by Chris Sawtell</h1> +This copy was taken in May 94. The latest version is available +by +<a href=ftp://garbo.uwasa.fi/pc/c-lang/c-lesson.zip>clicking here</a> +<hr> +<dd><img src=../../../GRAPHICS/whiteball.gif> +<a href=c-lesson.1> Introduction</a> +<dd><img src=../../../GRAPHICS/whiteball.gif> +<a href=c-lesson.2> History</a> +<dd><img src=../../../GRAPHICS/whiteball.gif> +<a href=c-lesson.3> Data Storage.</a> +<dd><img src=../../../GRAPHICS/whiteball.gif> +<a href=c-lesson.4> Arrays & Pointers</a> +<dd><img src=../../../GRAPHICS/whiteball.gif> +<a href=c-lesson.5> Operators</a> +<dd><img src=../../../GRAPHICS/whiteball.gif> +<a href=c-lesson.6> Pre-processor</a> +<dd><img src=../../../GRAPHICS/whiteball.gif> +<a href=c-lesson.7> Libraries</a> +<dd><img src=../../../GRAPHICS/whiteball.gif> +<a href=c-lesson.8> Debugging</a> +<dd><img src=../../../GRAPHICS/whiteball.gif> +<a href=c-lesson.9> Structure</a> |