Annotations on K&R II
This webpage and all pages below
it appear as a
matter of record only. My current website (as of 2017-05-26) is at https://web.cs.dal.ca/~jamie/.
This document contains the following sections and subsections:
Upon re-reading The C Programming Language (second
edition) by Brian W. Kernighan and Dennis M. Ritchie
(aka K&R II) I was surprised to find it much
richer than I had remembered. I took the uncharacteristic step
of writing notes in the margins of my copy. Some of those notes
are reproduced below in the hopes
that others will find them helpful too.
I don't want to give the impression that K&R II should replace
the ISO Standard or the ANSI Rationale. I use
K&R II as an introduction and tutorial to the C language.
Experienced C programmers will find Harbison and Steele's C: A Reference Manual a
better reference work (in my opinion, of course). The Standard is,
as its title implies, the definition of the modern C
language. Harbison and Steele provide descriptions of both
ISO/ANSI and
pre-ANSI C, by the way.
Note that K&R II describes the 1989/1990 version of the
ANSI/ISO C
standard. In 1999 a new C standard (ISO/IEC
9899:1999) was approved by the ISO. I am not yet
in a position to recommend a good reference to the new standard
(other than itself). My understanding is that the only change in the
new standard that could break old code is that //
can
now be used to begin a single-line comment. The mavens in the
comp.lang.c.moderated newsgroup (Douglas Gwyn and Dan Pop
in particular) know much more about this than I do.
Below are some notes I use myself as a mini index.
- Array bounds
- pp. 100, 103
- Arrays are row major (final dimension varies
fastest)
- p. 112
- Boolean values (
0 ==
FALSE)
- p. 42
- Brace style
- p. 10
- printf() string precision examples
- p.154
I think Harbison and
Steele is a better reference work about C
than K&R is, but there are still some times when I prefer
the tables in K&R. So I've put together a seperate document
with a list of index of the tables I have written on page viii
of my copy of K&R. That document uses the HTML table
standard described in the HTML 3.2 standard. I
also have a plaintext version. Use whichever you prefer:
Once upon a time, Greg Haley had online versions of all of the tables.
My list of recommended
books about computer programming includes full citation
information about the books mentioned above and references to
other online C resources. My example of how to encapsulate data types in C might interest
you. It uses lots of stuff from K&R II.
Steve Summit has written a course about C programming largely consisting of
annotations on K&R II (and another course that is largely independent of outside references).
The errata
notices are helpful too.
Once upon a time Greg Haley had online versions of all of the tables.
Richard Heathfield maintains a list of Answers
to Exercises from the book. Those answers are separate from
those in The C Answer Book (2e) (by Clovis L. Tondo and
Scott E. Gimpel, published and copyright by Prentice-Hall 1989) and,
most importantly, some of the answers take account of the 1999 C Standard.
I've listed my annotations in three parts: clarifications, cross-references
and scattered
discussions. Also, I keep a very short list of so-called quick-references
above.
- p. 6
- main() should have a return (see pp. 26
and 164)
- p. 9
- comments do not nest (see p. 34)
- p. 10
- The difference between semicolons in C and other
languages, especially Pascal, is further explained on p. 55
- pp. 53 - 54
- The behaviour of code like
a[i] = i++;
is
not unspecified, it is undefined!
This example is discussed in two sections of Steve Summit's
comp.lang.c FAQ: Section 3 (`Expressions')
explains why that code, and variations on it, are abominable.
The book version of the FAQ list has some very clear advice
on what to avoid when programming expressions; Section 11
(`ANSI/ISO
Standard C') in the online list (and the book of course) explains the
differences between implementation-defined, unspecified, and
undefined behavior and why they exist.
- p. 90
- ## and # are used during macro expansion only. The comp.lang.c FAQ has something to say about this point.
- pp. 94, 103, 120
- void * cannot hold function pointers. For
further clarification within K&R II see Sections A6.8
(Pointers to Void on p. 199), A.4 (Meaning
of Identifiers on p. 195) and A.5 (Objects and
Lvalues on p. 197).
- p. 126 (Excercise 5-20)
- Before you try incorporating const into
dcl see my comment on p. 146.
(const was introduced on p. 40.)
- p. 135
- sizeof is better defined in Section A7.4.8
(Sizeof Operator, on p. 204).
- p. 143
- I think that a user supplied definition of
strdup() (which is not in the standard library by
the way) would violate the ISO standard for function names.
Steve Summit wrote about this in question 1.29 (pp. 23 - 26)
of C Programming FAQs.
- p. 146
- Be wary of using const with typedef:
const qualifies the whole type encapsulated with
typedef. For example `typedef char * String; const
String cs' means the same as `char * const cs' (a
constant pointer) not `const char * cs' (a pointer to a
constant character).
- p. 159
- I find the statement that
an array name is a pointer
misleading. See p. 99 for the details.
- p. 119
- Note that: (1) char * is not the same as void * and
(2) this qsort() is not necessarily the
same as the standard library's. (I got these points from a
comment on p. 229 (question 13.8) of Steve Summit's C Programming FAQs.)
- p. 142
- It is not necessary to cast the values returned by
malloc in ANSI C. In fact it can make it hard to detect
certain programming errors (caused by not including appropriate
headers).
- The same note applies to p. 167.
- p. 163
- Also, by default, stderr is unbuffered (p. 168)
- pp. 164, 247
- You are well advised not to use gets() as it
cannot check for overflow. See question 12.23 on pp. 208 - 209
of Steve Summit's C Programming FAQs (or the online version) for more details.
- p. 167
- Peter Seebach has (or at least had on 6 May 1996) this
comment on his so-called Useless K&R Page:
It
is asserted that the pointer returned by malloc
or calloc
must be converted to an appropriate
type; this is not true in ANSI C.
- p. 183
- size_t is defined in <stddef.h>
(pp. 260-1). (<sys/types.h> is not part of
the ANSI/ISO C
standard libraries, although it may be in the
POSIX standard.)
- p. 241
- Peter Seebach has (or at least had on 6 May 1996) this
comment on his so-called Useless K&R Page:
Of course, actually the library is a part of the language, and
although it must be possible to take the address of the functions
in the library, a compiler is allowed to inline and optimize
calls, and many do. However, it is a part of the language
definition. (Of course, it's not a part of a freestanding
implementation; in this respect, the book is correct.)
- p. 244 (Table B-1)
x,X
: argument must be unsigned. (An erratum
that was included in the official errata list on 29 October 1998. Thanks to Dan
Pop and Tanmoy Bhattacharya for pointing this out in
comp.lang.c.)
- pp. 247
- Don't use gets(). See my note for p. 164 for more details.
- p. 255
- tm_sec: the committee mistakenly thought there could be
as many as 2 leap seconds in one minute (thanks to Richard A. O'Keefe
for the explanation)
- p. 257
- %S: the committee mistakenly thought there could be as
many as 2 leap seconds in one minute (thanks to Richard A. O'Keefe
for the explanation)
I found the errata notices helpful too.
I've included references to expanded definitions that appear later
in the text. My copy also has exact page numbers for many of the
cross-references by section, but there is no point to including those
here.
- p. 14 (Section 1.4: Symbolic Constants)
- See bottom of p. 39 for discussion of an alternative (using enum)
- p. 26
- The conventional interpretation of the return
statement appears at the top of p. 164.
- p. 33
- See extern declarations below
- p. 38
- More about string constants on p. 104
- p. 40
- The definition of static is on p. 83
- p. 40
- variable initialization is dealt with on p. 85
- p. 42
- NULL is equivalent to zero in this context (see p. 102)
- p. 48 (Section 2.9: Bitwise Operators)
- see also Section 6.9 (Bit-fields) on pp. 149 - 150
- p. 48
- There is an example of operator precedence on p. 52 (Section 2.12)
- p. 63
- A different swap appears on p. 96
- p. 68
- Pointers are discussed in Chapter 5
- p. 73
- For information about type conversion by return
see the top of p. 255 and Section A6.5 (Arithmetic
Conversions) on p. 198
- p. 83 (Section 4.7: Register Variables)
- Even though the compiler is free to ignore the
declaration register variables can be used as
documentation that the variables will be heavily used and that
their addresses will not be computed, e.g. the &
operator will not be applied to them.
- p. 77
- See extern declarations below
- p. 80
- See extern declarations below
- pp. 91, 103
- sizeof is explained on p. 135
- p. 96
- Compare this swap with pp. 62 - 3 and p. 88
- p. 100
- Regarding array bounds see also the top of p. 103 and the
example (and accompanying text) on p. 138
- p. 101
- static variables are defined on p. 83
- p. 104
- string constants are static (see Section A2.6 on p. 194)
- p. 110 (Section 5.7: Multi-dimensional Arrays)
- See also Section A.6.2 (Array Declarators on pp. 216-7)
- p. 135 NKEYS macro
- What if an array is passed to a function? (See the paragraph
beginning
When an array name is passed to a function...
on
p. 99, and the binsearch() on p. 137.) [Although K&R make this
point clearly some discussion in the comp.lang.c
newsgroup makes me think that I should take extra steps to make
sure that it stands out. (Jan 1998)]
- p. 137 (binsearch())
- Note that the size (int n) is still needed because the
array's size cannot be determined when it is passed to a function
(see p. 99).
- p. 165
- register declaration introduced on p. 83
- p. 174
- Section 7.6: Error Handling -- Stderr and Exit is on pp. 163-4
- Section 7.3: Variable-length Argument Lists is on pp. 155-6
- See also Errors: detecting and handling below
- p. 243-245
- The examples of printf() in Section 7.2 (pp. 153-155) are helpful
- introduced on
- p. 33
- example on
- p. 77
- additional discussion on
- p. 80 (Section 4.4)
- Returns from functions should be checked for errors
- p. 141
- An example of an error indication being passed on to the caller
- p. 143
- Useful values should be returned from programs
- p. 164
- error(): an example of a general error-reporting function
- p. 174
- I prefer my version
- EXIT_SUCCESS and EXIT_FAILURE mentioned
- p. 252
References
Full citation information for any works cited above can be found in my list of recommended books about computer programming that I
mentioned at the top of this document. The Taylor library at UWO has a
copy of the ISO/ANSI standard
(989:1990(E), approved 3 Aug 1992) at shelf location QA76.73.C15 A44 1990.
The See also section above may also be of interest to you.
Last updated by J. Blustein on 04 November 2001
This document is copyright by its author, J. Blustein
<jamie@csd.uwo.ca>.