Errata list for "C Programming FAQs: Frequently Asked Questions",
by Steve Summit, Addison-Wesley, 1996, ISBN 0-201-84519-9
(first printing).

A possibly more up-to-date copy of this errata list may be
obtained at any time by anonymous ftp from
in the file ~scs/C-faq/book/Errata, or on the web at .
(If you read this years from now and those addresses don't
work, try or .)

scs 2002-Oct-26

page	question
----	--------

front cover	The ladder has no rungs.

xxix		"woundn't" should be "wouldn't"

2	1.1	The fourth bulleted guarantee (about the sizes
		following the "obvious progression") is
		improperly stated.  What the C Standard actually
		talks about, as in the rest of this answer, is
		just the ranges of the standard types, not their
		sizes in bits.  So the real guarantees (as
		summarized below) are that

			sizeof(char)  is at least 8 bits
			sizeof(short) is at least 16 bits
			sizeof(int)   is at least 16 bits
			sizeof(long)  is at least 32 bits

		and, in C99,

			sizeof(long long) is at least 64 bits

3-4	1.3	In C99, the new <inttypes.h> header provides
		Standard names for exact-size types: int16_t,
		uint32_t, etc.

4	1.4	In C99, long long is defined as an integer type
		with, in effect, at least 64 bits.

6	1.7	There may be zero definitions of an external
		function or variable that is not referenced
		in any expression.
		[Thanks and $1 to James Stern]

7	1.7	"use include to bring" should be
		"use #include to bring"

11	1.14	In the second fix, at the bottom of the page,
		it could conceivably be necessary to precede
		the line

			typedef struct node *NODEPTR;

		with the line

			struct node;

		for the reason mentioned on page 13, although
		in that case one of the two other fixes would
		clearly be preferable.
		[Thanks to James Stern]

13	1.15	In the alternate fix, at the bottom of the page,
		it could conceivably be necessary to precede
		the typedef declarations with the lines

			struct a;
			struct b;

		although again, putting those typedefs after the
		complete structure definitions would clearly be
		preferable in that case.
		[Thanks to James Stern]

18	1.22	The odd "return 0;" line is not really necessary.

20	1.24	Another possible arrangement is

			/* file1.h */
			#define ARRAYSZ 3
			extern int array[ARRAYSZ];

			/* file1.c */
			#include "file1.h"
			int array[ARRAYSZ];

			/* file2.c"
			#include "file1.h"

		[Thanks to Jon Jagger]

23	1.29	[2nd bullet] "everything else termed" should be
		"everything else, termed"

24	1.29	[Rule 3] "if the header" should be "if any header".
		[Thanks and $1 to James Stern]

24	1.29	[Rule 4] "(i.e., function names)" should be
		"(e.g., function names)".
		[Thanks and $1 to James Stern]

24	1.29	The text at the bottom of the page suggests that
		"future directions" name patterns such as str[a-z]*
		are reserved only if their corresponding headers
		(e.g. <stdlib.h>) are included.  The reserved
		function names are unconditionally reserved;
		it is only the macro names that are reserved only
		if the header is included.
		[Thanks and $1 to Mark Brader]

25	1.29	"if you don't include the header files" should be
		"if you don't include any header files".

32	2.4	Besides -> and sizeof, the . operator, as well as
		declarations of actual structures, also require
		the compiler to know more about the structure and
		so preclude incomplete or hidden definitions.
		[Thanks to James Stern]

33-36	2.6	In C99, a structure can contain a variable-length
		array (VLA) as its last member, providing a
		well-defined, Standard-compliant alternative.

38	2.10	C99 *does* have a way of generating anonymous
		structure values: "compound literals".

40	2.12	When trying to minimize wasted space in structures,
		array members should be ordered based on the size
		of their primitive types, not their overall size.
		[Thanks and $1 to James Stern]

43	2.20	"ANSI/SIO" should be "ANSI/ISO"

		In C99, the "designated initializer" mechanism
		allows any member of a union to be initialized.

50	3.3	Of course, another way to increment i is i += 1.
		[Thanks to James Stern]

51	3.4	"higher precedence than *):" should be
		"higher precedence than *:"

52	3.6	Delete the close parenthesis at the end of the answer.

57	3.12	In C++, the prefix form ++i is preferred.
		[Thanks to James Stern]

68	4.5	The reference to ANSI Sec. 3.3.4 should say
		"esp. footnote 44".
		[Thanks to Willis Gooch]

72-3	4.10	In C99, it is possible to use a "compound
		literal" to generate a pointer to an (unnamed)
		constant value.

73	4.11	The reference to K&R2 sec. 5.2 should be pp. 95-7.
		[Thanks and $1 to Nikos Triantafillis]

75	4.13	"can interconverted" should be "can be interconverted".
		[Thanks and $1 to Howard Ham]

84	5.8	Either the comma or the parentheses in the answer
		should be changed.

95	6.2	The typography in the following line is inconsistent
		for the "x" of "x[3]".

104-5	6.15	C99 introduces variable-length arrays (VLA's) which,
		among other things, *do* allow declaration of a
		local array of size matching a passed-in array.

105-7	6.16	In C99, another solution is to use a
		variable-length array.

110	6.19	C99's variable-length arrays are also a nice
		solution to this problem.

115	7.1	The close parenthesis and period ")." at the bottom
		of the page are not part of the #define line.

121	7.9	There is an extra semicolon at the end of the first
		line of mymalloc's definition.
		[Thanks and $1 to Todd Burruss]

126	7.10	Missing "it"; should be "even if it is not
		[Thanks and $1 to Clinton Sheppard]

132	7.30	It would be even safer to add a second test on

			if(nchread >= nchmax) {
				nchmax += 20;
				if(nchread >= nchmax) {
					return NULL;
				newbuf = realloc(retbuf, nchmax + 1);

		The concern is that, while reading a *very* long line,
		nchmax might overflow, wrapping back around to 0.
		[Thanks to Mark Brader]

134	7.32	C99's variable-length arrays (VLA's) can be used
		to more cleanly accomplish most of the tasks
		which alloca used to be put to.

136	8.1	"Although string literal" should be
		"Although a string literal"

136	8.2	C can be tricked into seeming to assign an array
		as a whole if you hide the array inside a
		structure or union.
		[Thanks and $1 to James Stern]

143	9.2	The example variable isvegetable should perhaps
		be named is_vegetable to avoid naming conflicts
		(see question 1.29).
		[Thanks and $1 to Jon Jagger]

151	10.4	Extra space in "/* (no trailing ; ) */".

152	10.6	[paragraph below bullets] "bring the header wherever"
		should be "bring the header in wherever"

158	10.15	If you have to, you can obviously #define a companion
		macro name for each typedef, and use #ifdef with that.
		[Thanks to James Stern]

161	10.21	The suggested replacement macro should
		parenthesize c:

			#define CTRL(c) ((c) & 037)

		[Thanks and $1 to James Stern]

163-4	10.29	C99 introduces formal support for macros with
		variable numbers of arguments.

164-5	10.27	The file parameter of the dbginfo() function and
		the fmt parameter of the debug() function could
		be of type const char *.
		[Thanks to James Stern]

168	11.1	The story has gotten longer: A new revision of
		the C Standard, "C99", has been ratified,
		superseding the original ANSI C Standard.
		This Errata list has been updated to note those
		answers in the book which have become dated due
		to C99 changes.

169-70	11.2	C99 *is* available in electronic form, for $18
		from .

174	11.10	As written, the "complicated series of assignments"
		of course includes some declarations and initializations.
		[Thanks to James Stern]

175	11.10	"e.g., (const char) ** in this case" should be
		"e.g., (const char **) in this case"

		"when the pointers which" should either be
		"when the pointers" or "with pointers which"

180	11.19	"questions 20.20" should be "question 20.20"

182	11.25	"The function offers" should be
		"The memmove function offers".
		[Thanks and $1 to Gordon Burditt]

183-4	11.27	In C99, external identifiers are required
		to be unique in the first 32 characters;
		C90's extremely Spartan limitation to six
		characters has been relaxed.

186	11.29	You may also need to rework calls to realloc
		that use NULL or 0 as first or second arguments
		(see question 7.30).

186	11.29	You may also need to rework conditional compilation
		involving #elif.
		See also the Rationale's list of "Quiet Changes"
		(see question 11.2).
		[Thanks to James Stern]

189	11.33	A fourth class of behavior is locale-specific.
		[Thanks and $1 to James Stern]

198	12.11	A semicolon is missing after "int i = 0".

		The } just before the line "*p = '\0'" is
		indented one tab too few.

		Two instances of "*--p" have the minus signs merged
		so as to appear as one.

201	12.16	[case 2] The variable line is not declared;
		it should probably be a char [], suitably
		initialized, e.g.:

			char line[] = "1 2.3 4.5e6 789e10";

		[Thanks and $1 to James Stern]

205	12.19	There's an extraneous double quote in what
		should be "intervening whitespace:".

207-8	12.21	The technique of writing to a file may give the
		wrong answer if the disk fills up.
		[Thanks and $1 to Mark Brader]

		The "hope that a future revision of the ANSI/ISO
		C Standard will include" the snprintf function
		has been fulfilled: C99 does specify it.
		As a bonus, the C99 snprintf can be used to predict
		the size required for an arbitrary sprintf call,
		too -- it can be called with a null pointer
		instead of a destination buffer (and 0 as the
		size of that nonexistent buffer) and it returns
		the number of characters it would have written.

212	12.28	The answer is in the wrong font.

213	12.30	Updating (overwriting) a text file in-place is
		not fully portable; the C Standard leaves it
		implementation-defined whether a write to a
		text file truncates it at that point.
		[Thanks and $1 to Tanmoy Bhattacharya]

224	13.4	"upper- or lowercase" should probably be
		"upper or lower case".

225	13.6	Since the fragment calls printf, it must
		#include <stdio.h>.
		[Thanks and $1 to James Stern]

226	13.6	[last code fragment] A declaration and initialization

			char string[] = "this\thas\t\tmissing\tfield";

		similar to the one on p. 225 should appear.
		[Thanks and $1 to Doug Liu]

227	13.6	Also, since the input string is modified,
		it must be writable; see question 1.32.

234	13.14	"time_ts" should perhaps be "time_t's"

240	13.17	The code

			srand((unsigned int)time((time_t *)NULL));

		though popular and generally effective is, alas,
		not strictly conforming.  It's theoretically
		possible that time_t could be defined as a
		floating-point type under some implementation,
		and that the time_t values returned by time()
		could therefore exceed the range of an unsigned
		int in such a way that a well-defined cast to
		(unsigned int) is not possible.

242-3	13.20	The attributions listed for methods 2 and 3 are
		scrambled.  Method 2 is the one described in
		the 1958 Box and Muller paper (as well as by
		Abramowitz and Stegun, apparently).  Method 3
		is originally due to Marsaglia.

244	13.21	If you're not familiar with the notation [0, 1),
		it means that drand48() returns a number x
		such that 0 <= x and x < 1.

250	14.5	The suggested expression should read

			fabs(a - b) <= epsilon * fabs(a)

		It performs poorly if a == 0.0 (which is another
		argument in favor of "mak[ing] the threshold
		a function of b, or of both a and b").

253	14.8	Of course, you can always compute pi using
		4*atan(1.0) or acos(-1.0).
		[Thanks to James Stern and Clinton Sheppard]

253	14.9	C99 specifies isnan() and several other
		classification routines.

254-5	14.11	C99 supports complex as a standard type.

260-1	15.4	The first argument to vstrcat() could be const char *,
		as could the fmt argument to miniprintf().
		[Thanks to James Stern]

264	15.5	The fmt argument to error() could be const char *.

269-71	15.12	The fmt arguments to faterror(), verror(), and
		error() could all be const char *.

274	16.4	[point 2] The problem could be caused by a setbuf
		or setvbuf buffer local to any function.
		[Thanks and $1 to James Stern]

276	16.7	Variable "s" isn't declared.  It's pretty obvious
		what it should be, but to make it explicit, change
		the struct declaration to

			struct mystruct { ... } s;

		[Thanks to Peter Hryczanek]

287	18.1	The URL in the list of metrics tools is really

294	18.13	The conventional spelling is "NetBSD".
		[Thanks and $1 to Peter Seebach]

294	18.14	Extra space in site which should be "".

296	18.16	Extra space in address which should be

308	19.11	Note that a test using fopen() *is* approximate;
		failure does not necessarily indicate nonexistence.

310	19.14	Updating (overwriting) a text file in-place is
		not fully portable; the C Standard leaves it
		implementation-defined whether a write to a
		text file truncates it at that point.
		[Thanks and $1 to Tanmoy Bhattacharya]

314	19.23	In C99, the guarantee on the possible size of a
		single object has been raised to 64K.

315	19.25	Use of the `volatile' qualifier is often
		appropriate when performing memory-mapped I/O.
		[Thanks to Lee Crawford]

317	19.27	The return value of system() is not guaranteed
		to be the command's exit status.
		[Thanks and $1 to Peter Seebach]

318	19.30	If you forget to call pclose, it's probably at
		least as likely that you'll run out of file
		descriptors as processes.
		[Thanks and $1 to Jens Schweikhardt]

319	19.31	argv[0] may also be a null pointer.
		[Thanks and $1 to Tanmoy Bhattacharya]

324	19.42	"control characters, such as" should be
		"control characters such as"

339-40		The page break makes the code very hard to follow.

342-44	20.13	The tone of this question's answer can be read as
		suggesting that efficiency isn't important at all.
		That's not the case, of course -- efficiency can
		very important, and poorly-written programs can
		run abysmally inefficiently.

		The point is that there are good ways and bad
		ways of achieving an appropriate level of
		performance for a given program, and that (for
		example) picking a good algorithm tends to make a
		much bigger difference than does microoptimizing
		the coding details of a lesser algorithm.

346	20.17	Missing tab in line which should be

			#define CODE_NONE	0

350	20.21	The overbars are misaligned.

355	20.29	"and computes that number" should either be
		"computed" or "and is computed".

363		[aggregate] Unions are not aggregates.
		[Thanks and $1 to Kinichi Kitano]

368		[parameter] Extraneous semicolon at end of
		line which should be

			f(int i)

370-1		The glossary entry for "undefined" is misplaced.
		[Thanks and $1 to James Stern]

376		The two minus signs in the index entry for
		"-- operator" overlap and appear to be one.

379		The pairs of underscores in the index entry for
		"__FILE__ macro" overlap and might appear to be one.

382		The pairs of underscores in the index entry for
		"__LINE__ macro" overlap and might appear to be one.

back cover	"on the Usenet/Internet on the C FAQ" is muddled
		and should say something else.

		"com.lang.c" should be "comp.lang.c".

		The ftp address for source code should be .

more information about this book
on-line version of FAQ list
scs home page