Errata

21st Century C

Errata for 21st Century C

Submit your own errata for this product.

The errata list is a list of errors and their corrections that were found after the product was released. If the error was corrected in a later version or reprint the date of the correction will be displayed in the column titled "Date Corrected".

The following errata were submitted by our customers and approved as valid errors by the author or editor.

Color key: Serious technical mistake Minor technical mistake Language or formatting error Typo Question Note Update

Version Location Description Submitted By Date submitted Date corrected
PDF
Page iv, 71

"Describing the Makefile with makefile.am"

In all other occurrences Makefile.am is capitalized.

Note from the Author or Editor:
fixed in repo

agezerlis  Nov 05, 2012  Jan 18, 2013
Chapter 1
"Here Documents" section - Note

The Note states that single quotes are needed around the dash in the following command, so that Python knows it's not the start of a flag:

echo "print 'hi.'" | python '-'

However, those quotes are stripped off by the shell before Python ever sees the dash. The command runs the same with or without the quotes.

Note from the Author or Editor:
Good point.

Fixed by BK.

Russell Reed  Apr 16, 2013  Jun 14, 2013
PDF
Page 3-4
bottom half

The lower part of p. 3 has a set of bullet points covering the agenda for this chapter.

All of these are repeated in the first half of p. 4. Apparently the only differences are the presence of the words "Environment variables" and "A simpler compilation system" on p. 4.

Note from the Author or Editor:
we stopped the presses for this one. fixed in the print edition.

Alex Gezerlis  Oct 15, 2012  Jan 18, 2013
PDF
Page 6
near the middle

"you will have a complete development system are and ready to get coding."

The words "are" and "and" should be interchanged.

Note from the Author or Editor:
fixed in the repository in october.

Alex Gezerlis  Oct 15, 2012  Jan 18, 2013
ePub
Page 7/48
United States

"Cultivate Robust and Flourishing Macros" suggests enclosing multi-line macros in braces to avoid control flow gotchas, but the suggested construction, e.g.

#define myMacro() { \
... \
}

will break in the case of

if (x)
myMacro();
else
...

The canonical way to define such macros is:

#define myMacro() do { \
... \
} while (0)

Note from the Author or Editor:
I never liked the look of the do-while, but I concede that it is better to have it there.

Additional text added by BK. Also, added a do-while wrapper to the Stopif macro in the book and the sample code.

Michael Chock  Jan 23, 2013  Jun 14, 2013
PDF
Page 8
line 25 (line 3 in paragraph under "GNU" heading

"The great majority of Linux distributions use GCC tools throughout." GCC should be changed to GNU; as the paragraph goes on to note, GCC is just one of many GNU tools.

Note from the Author or Editor:
Fixed in the repository. Will appear online soon.

Matthew Abbott  Aug 23, 2012  Jan 18, 2013
PDF
Page 14
near the middle

"depends on a Basic Linear Algebra Subroutines (BLAS) library"

The S in BLAS stands for Subprograms. This should also be corrected in the index entry on p. 264. (And on p. 419 of "Modeling with data", too :-))

Note from the Author or Editor:
fixed in the print edition

Alex Gezerlis  Oct 15, 2012  Jan 18, 2013
PDF
Page 14
line 4

"so many langauges advertise a C interface" -> langauges should be languages

Note from the Author or Editor:
Fixed in the repository. Will appear online soon.

Robert H?ppner  Aug 17, 2012  Jan 18, 2013
PDF
Page 21
middle of page

CFLAGS=`pkg-config --cflags apophenia glib-2.0` -g -wall -std=gnu11 -O3

Wall should be capitalized.

Note from the Author or Editor:
fixed in the repository in october.

agezerlis  Oct 19, 2012  Jan 18, 2013
PDF
Page 23
The last paragraph

On OSX, the c99 command's -W option is used to specify the pointer size (either 32-bit or 64-bit), not to set the warning level.

Note from the Author or Editor:
fixed in the print edition

Edward Dorrington  Sep 06, 2012  Jan 18, 2013
PDF
Page 25
United Kingdom

The program as written:

#include <time.h>
#include <stdio.h>
#include <stdlib.h>
int main(){
srandom(time(NULL)); // Initialize RNG seed.
printf("%li\n", random()); // Make one draw.
}

compiles with warnings, when the generalized makefile is used:

c99 -g -Wall -O3 random_draw.c -o random_draw
random_draw.c: In function ?main?:
random_draw.c:7:3: warning: implicit declaration of function ?srandom? [-Wimplicit-function-declaration]
random_draw.c:8:3: warning: implicit declaration of function ?random? [-Wimplicit-function-declaration]
random_draw.c:8:3: warning: format ?%li? expects argument of type ?long int?, but argument 2 has type ?int? [-Wformat]

-------

The following version will compile without warnings for the same makefile parameters:

#include<time.h>
#include<stdio.h>
#include<stdlib.h>

int main()
{
srand(time(NULL)); // initialize seed
long int x = rand();
printf("%li\n", x);
}


Note from the Author or Editor:
fixed in the print edition.

Michael O'Sullivan  Oct 03, 2012  Jan 18, 2013
PDF
Page 30
Last bulletitem

"...independent of th shell", missing an "e".

Note from the Author or Editor:
fixed in the print editon

Jonas  Sep 08, 2012  Jan 18, 2013
PDF
Page 36
last line of text

"structure representing and XML tree"

This should say "an".

Note from the Author or Editor:
fixed in the repository in october.

agezerlis  Oct 19, 2012  Jan 18, 2013
PDF
Page 42
entire

Lacuna between end of page 41 "Paste this onto your command
line, or add it to your .bashrc, .cshrc, &c.:" and beginning of page 43 / Chapter 3. Assume this is content that isn't finished yet, but no mention in the PDF or on the errata page of unfinished content.

Note from the Author or Editor:
Fixed in the repository. Will appear online soon.

Anonymous  Aug 24, 2012  Jan 18, 2013
PDF
Page 44
end of penultimate paragraph

"There reasons to not use the -g flag are rare indeed---it doesn?t slow down your program, and adding a kilobyte to your executable is irrelevant for most situations."

Maybe a missing "are" after "There"?

Note from the Author or Editor:
Fixed in the repository. Will appear online soon.

Robert H?ppner  Aug 17, 2012  Jan 18, 2013
PDF
Page 48
last paragraph

"That should be enough for you get started writing"

This is missing "to".

Note from the Author or Editor:
fixed. these have all been fixed.

agezerlis  Oct 19, 2012  Jan 18, 2013
Printed
Page 83
Example commands at bottom of page

In the section on branching, the branch that is worked on is intruduced as being "new_leaf" (with an underscore), but in the rest of the chapter it is referred to as being called "newleaf" (at the top of page 84: "git checkout newleaf" and first code example of the Merging section on page 84: "git merge newleaf").
For consistency the branch name should probably be changed to either "new_leaf" (more legible) or "newleaf".

Note from the Author or Editor:
Fixed in repo by BK.

Patrick Elsen  Feb 12, 2013  Jun 14, 2013
PDF
Page 85
2nd paragraph in Trees section

"It also means that list of commit objects on a branch"

This should say either "a" or "the" before "list".

Note from the Author or Editor:
the fix is in the repository, waiting to be pushed out.

agezerlis  Nov 05, 2012  Jan 18, 2013
PDF
Page 90
step 5

"Because these are often shell scripts that need no compilation, it is is a distinct variable from check_PROGRAMS,"

Repetition of "is".

Note from the Author or Editor:
Fixed in the repository. Will appear online soon.

Robert H?ppner  Aug 19, 2012  Jan 18, 2013
PDF
Page 96
Sixth line up from bottom

"libray" should be "library"

Note from the Author or Editor:
fixed in the print edition.

Danny McAllaster  Sep 26, 2012  Jan 18, 2013
PDF
Page 97

"1 These lines check for Python, setting a PYTHON variable to : if it exists"

The first line sets PYTHON to : if Python does *not* exist:

AM_PATH_PYTHON ([VERSION], [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])

Note from the Author or Editor:
fixed in repo

agezerlis  Nov 05, 2012  Jan 18, 2013
PDF
Page 97

"2 If the Python variable is set"

The variable is called PYTHON, in capitals.

Note from the Author or Editor:
fixed in repo

agezerlis  Nov 05, 2012  Jan 18, 2013
PDF
Page 97
2nd paragrahp

"It get some support from the index,": get -> gets

Note from the Author or Editor:
Fixed in the repository. Will appear online soon.

Robert H?ppner  Aug 19, 2012  Jan 18, 2013
PDF
Page 98
end of 6th paragraph

"to add to the index chages to all the files Git already tracks.": chages -> changes

Note from the Author or Editor:
Fixed in the repository. Will appear online soon.

Robert H?ppner  Aug 19, 2012  Jan 18, 2013
Printed
Page 105
DE

The example code for aliasing is broken.
The array of structs (your_data) is used wrong.
your_data[0]->matrix->data[0]
should be
your_data[0].matrix->data[0]
or
your_data->matrix->data[0]

The next line of code is broken, too. The syntax error is the same as mentioned before. Anyway, there is another error. The line (with corrected access)
double *elmt1 = your_data[0].matrix->data[0]
has a syntax error. On the right is a value and on the left a pointer. The line should be
for a copy:
double elmt1 = your_data[0].matrix->data[0]
or for a reference (or alias):
double *elmt1 = &your_data[0].matrix->data[0]

Anyway the code is ill thought through. In the struct
typedef struct {
gsl_vector *vector;
gsl_matrix *matrix;
} datapair;
The members vector and matrix are uninitialized pointers. Therefore the code may segfault or at least cause havoc in the program.

Note from the Author or Editor:
fixed in repo.

Anonymous  Nov 25, 2012  Jan 18, 2013
PDF
Page 111
Example 6.6, note 2

The note number 2 reads: The address of the first element, assigned to a new pointer.
The corresponding line of code:
int *positive_evens = &evens[1];
actually addresses to the second element, since array indexes start with 0 and not 1.

Note from the Author or Editor:
Good point. I've reworded the text to correct this.

Hector Zarate  Sep 25, 2012  Jan 18, 2013
PDF
Page 113
2nd Paragraph (Code Sample) and 3rd Paragraph

Inside the definition of function f() and the next paragraph on page 113:
"a_list" should be "in".

int f(void *in){
if (*(int*)in==0) return 1;
else return 1 + f(&(a_list[1])); //This won't work.
}
The base-plus-offset rule explains why this won?t work. To refer to a_list[1], the
compiler needs to know the exact length of a_list[0], so it knows how far to offset
from the base. But without a type attached, it can?t calculate that size.

Should be:
int f(void *in){
if (*(int*)in==0) return 1;
else return 1 + f(&(in[1])); //This won't work.
}
The base-plus-offset rule explains why this won?t work. To refer to in[1], the
compiler needs to know the exact length of in[0], so it knows how far to offset
from the base. But without a type attached, it can?t calculate that size.

Note from the Author or Editor:
Yes.

Fixed in repo by BK.

Anonymous  Jun 03, 2013  Jun 14, 2013
PDF
Page 117
penultimate bullet point

"So The Make file.am for the py directory": the first occurrence of "The" is wrongfully capitalized

Note from the Author or Editor:
Fixed in the repository. Will appear online soon.

Robert H?ppner  Aug 19, 2012  Jan 18, 2013
PDF
Page 118
center

"Set Array Size at Runtime
Dovetailing with putting decarations"

decarations -> declarations

Note from the Author or Editor:
fixed in the print edition.

laurent@lafage.org  Sep 26, 2012  Jan 18, 2013
PDF
Page 120
second to last paragraph

The sentence claims that five symbols (ordinary identifiers) are added to the global space, directions and the values the enum can take. However, directions is added to the namespace for tags, for structures, unions, and enums, not the global space.

See the C11 standard section 6.2.3(1).

Note from the Author or Editor:
fixed in repo

mattwidmann  Nov 25, 2012  Jan 18, 2013
PDF
Page 129
1st paragraph

"But if you think there’s even a remote possibility that you have a variable that might multiply its way up to the billions [...] then you certainly need to use a long int or even a long long int, or else your answer won’t just be imprecise—it’ll be entirely wrong, as C suddenly wraps around from +2.1 billion to -2.1 billion."

The author may want to avoid implying that this overflow behaviour is reliable and can be depended on, since signed integer overflow is Undefined Behaviour.

Note from the Author or Editor:
Reworded in 2nd ed to: "...it’ll be entirely wrong, as most implementations wrap around from +2.1 billion to -2.1 billion"

Daniel Bedrenko  Jun 20, 2017 
PDF
Page 133
center of the page

"By the way, there can?t be padding at the beginning of a struct, so so": "so" is repeated

Note from the Author or Editor:
Fixed in the repository. Will appear online soon.

Robert H?ppner  Aug 21, 2012  Jan 18, 2013
PDF
Page 133
center of the page

Hello,

If I test:

"The header stddef.h defines the offsetof macro, which makes the base-plus-offset thinking accurate again: list[2].d really is at list + 2*sizeof(abcd_s) + offsetof(abcd_s, d)"

It doesn't work:

list[0].a (0x7fff646e0560) is located at list (0x7fff646e0560) <- ok

but:

list[2].d (0x7fff646e05a0) is located at list + 2*sizeof(abcd_s) + offsetof(abcd_s, d)) (0x7fff646e0b60) <- not ok

Maybe I am wrong (in this case, this paragraph need some clarification or more code ;)), do you have an explanation ?

Thanks !

PS: my test program:

#include <stdlib.h>
#include <stddef.h>
#include <stdio.h>
#include <assert.h>

typedef struct {
int a, b;
double c, d;
} abcd_s;

int main(void) {
abcd_s list[3];
printf("list[0].a (%p) is located at list (%p)\n", &list[0].a, list);
printf("list[2].d (%p) is located at list + 2*sizeof(abcd_s) + offsetof(abcd_s, d)) (%p)\n",
&list[2].d,
list + 2*sizeof(abcd_s) + offsetof(abcd_s, d));
assert(&list[2].d == list + 2*sizeof(abcd_s) + offsetof(abcd_s, d));
return EXIT_SUCCESS;
}



Note from the Author or Editor:
This code:
list +3
is equivalent to list[3], so calling list+2*sizeof(abcd_s) is equivalent to something like list[48].

We need to force the compiler to read the address of list as a number, so it does plain arithmetic rather than pointer arithmetic. This assertion will work:

assert(&list[2].d == ((size_t)&list) + 2*sizeof(abcd_s) + offsetof(abcd_s, d));

I've rewritten the text to clarify.

laurent@lafage.org  Sep 26, 2012  Jan 18, 2013
Printed
Page 134
Germany

On that page, in the box "Macro Arguments Are Optional", a macro is described which is implemented like this:
[...] fprintf(stderr, #assertion "failed to be true. \
Returning" #returnval "\n"); [...]

The main string in this macro needs to have spaces at the beginning and at the end, like this:
[...] fprintf(stderr, #assertion " failed to be true. \
Returning " #returnval "\n"); [...]

Otherwise, assuming that #assertion is "a==b" and #retval is "9", The macro will pass a string to fprintf that looks like this:
"a==bfailed to be true. Returning9"
due to the fact that when the preprocessor joins adjacent strings, it does not add spacing between the added string.

Note from the Author or Editor:
Fixed in repo by BK.

Patrick Elsen  Feb 19, 2013  Jun 14, 2013
Printed
Page 150
Bottom of the page, section "A keyword for the Morbid"

In that section the function "at_exit" is introduced, but in reality it doesn't exist. What exists is "atexit" (note the missing underscore in the middle).

"man" and general googling seems to confirm this.

Note from the Author or Editor:
Good catch! The correct names are at_quick_exit and atexit.

The Bauhaus-inspired sample code gets this right (otherwise it wouldn't compile and pass tests), but the text has the incorrect extra underscore.

Fixed by BK in 2nd ed commit b64f8fc.

Alfredo Di Napoli  Nov 03, 2015 
Printed
Page 157
code example 9-5

Funny indentation (#include <glib.h> is indented one less than the rest of the code)

Note from the Author or Editor:
O'Reilly's document prep system inserted a few line breaks and tabs here and there. Thanks for catching this one.

Fixed by BK.

Patrick Elsen  Feb 19, 2013  Jun 14, 2013
Printed
Page 158
Example description (1)

The book reads "Although it's doesn't", should be "Although it doesn't"

Note from the Author or Editor:
Fixed in repo by BK.

Markus Wamser  May 17, 2013  Jun 14, 2013
Printed
Page 159
last line of text

The opening bracket of "(b)" after "Hebrew &#1468;&#1489;" is typeset in bold where only the "&#1468;&#1489;" should appear in bold.

Note from the Author or Editor:
Dear Toolsreq: this seems to be a bug somewhere in the typesetting system, because the XML is correct:

Hebrew &#1489;&#1468; (<emphasis>b</emphasis>)

Fixed in repo by BK by rewriting. Is also more consistent with later text now.

Markus Wamser  May 17, 2013  Jun 14, 2013
Printed
Page 159
1st sentence on the page

The first sentence on the page is incorrect, due to the incorrect usage of the term glyph. A glyph can have multiple code points. For example, the glyph &#8721; can be represented by the mathematical U+2211 or the Greek U+03A3. There is not a one-to-one mapping between glyphs and code points.

The sentence is helpful as an introduction, but a footnote is warranted to explain that it is an oversimplification. Or perhaps delete the word "single".

Note from the Author or Editor:
Good point. As per commenter's suggestion, I removed the word "single".

Fixed in repo by BK.

David D Lowe  Nov 12, 2013 
PDF
Page 160
Footnotes

It is claimed that the C99 & C11 standard guarantee CHARBIT to be 8, citing §5.2.4.2.1(1). Yet the paragraph of that section states "The values [including CHAR_BIT] given below shall be replaced by constant expressions [...]", meaning that the values given for these macros are defined by the implementation.

Note from the Author or Editor:
These two points are not contradictory: the compiler is expected to replace the symbol CHAR_BIT with a constant expression, but that constant expression must be "8" or larger.

So it's possible that you could write a compiler where the symbol CHAR_BIT is replaced with "9"! But this is only in the realm of 'technically not impossible'. The intent of this sentence was to counter older texts that took some care to handle 7-bit chars, which are no longer a consideration either in the standard or in practice.

Daniel Bedrenko  Jun 18, 2017 
PDF
Page 162
5th paragraph, first line under subheading "The Sample Code"

"?to take in a file and break it into ?words,?,= by which I mean?" has ",=" after '"words,"', which should be removed.

Note from the Author or Editor:
fixed in repo

mattwidmann  Nov 26, 2012  Jan 18, 2013
PDF
Page 162
3rd paragraph, last sentence

"?like getting its type (alpha, numeric, etc.), con- verting it to upper/lower case, et cetera."

The language used for "et cetera" changes in the parenthesised list to "etc." Most of the book uses "et cetera" instead of "etc."

Note from the Author or Editor:
fixed in repo.

mattwidmann  Nov 26, 2012  Jan 18, 2013
PDF
Page 164
Gettext box, 1st paragraph

"?user-friendly software translates has translations of its text?"

"translates" should be removed and the text should read:

"?user-friendly software has translations of its text?"

Note from the Author or Editor:
fixed in repo.

mattwidmann  Nov 26, 2012  Jan 18, 2013
PDF
Page 166
5th paragraph, second to last and last line

"...has two ways
call it..."

There should be a "to" after "ways". The typo is on the line break.

Also, ? above means ... (it's a horizontal ellipsis, U+2026).

Note from the Author or Editor:
fixed in repository

mattwidmann  Nov 26, 2012  Jan 18, 2013
PDF
Page 168
First paragraph after code

There are no __FUNCTION__, __FILE__, or __LINE__ macros to be expanded in the code referenced. Perhaps they are missing?

Note from the Author or Editor:
Fixed in repo on 3 December

mattwidmann  Nov 26, 2012  Jan 18, 2013
PDF, ePub, Mobi
Page 168
code at top

The example function call

//sample usage:
Stopif(x<0 || x>1, "x has value %g, " "but it should be between zero and one.", x);

seems incorrect since the macro requires "error_action" as second argument.

Note from the Author or Editor:
fixed in repository months ago.

Markus Dittrich  Dec 01, 2012  Jan 18, 2013
PDF
Page 174
First code sample

`int ll[20] = {};`

The standard forbids empty initializer braces, this can be seen by compiling with `-Wpedantic`. This occurs in many parts of the book.

Note from the Author or Editor:
This is technically correct, but there is no ambiguity in the standard about how to handle zero initializers, so it works everywhere. I will add a footnote to clarify this and allow interested readers an alternative:

<footnote>
The lexical definition of the language in the standard disallows empty initializers like these. However, §6.7.9(21) is clear on what happens when there are too few initializers for a compound object, and applies unambiguously for the case of zero initializers. Every compiler handles them exactly as expected—compiler authors would have to go out of their way to make a zero-initializer list behave differently. Therefore, this book uses empty initializers freely. However, if you want to conform to the lexical definition more closely, just explicitly add the zero that §6.7.9(21) implicitly assumes, replacing {} with {0}.
</footnote>

Daniel Bedrenko  Jun 18, 2017 
Printed
Page 179
code example 10.8, function free_fall_energy

The computation of the free fall energy is wrong. The correct formula for the kinetic energy is E=(1/2) *mv^2. So the last but one line of the function should be

out.value = mass*velocity*velocity/2.;

Note from the Author or Editor:
fixed in repository .

Michael Defort  Jan 02, 2013  Jan 18, 2013
Printed
Page 188
bullet 3

Should be: out.rate = in.rate ? in.rate : 4.5;


Fixed by Ben K.

Ben Klemens
 
Apr 02, 2013  Jun 14, 2013
Printed
Page 189
makefile

"LDFLAGS=-lm" should read "LDLIBS=-lm".

Otherwise, due to the linking order, GNU Make 3.81 && gcc (Ubuntu/Linaro 4.7.2-2ubuntu1) 4.7.2 yield the linker error "undefined reference to `pow'".

Note from the Author or Editor:
I had a whole bit warning the user about using LDLIBS instead of LDFLAGS, and then I go and use LDFLAGS.

Fixed in repo by BK.

Werner Wenzel  Feb 27, 2013  Jun 14, 2013
Printed
Page 190
In "Functions with Generic Inputs": typedef example

Instead of:

typedef void *(*void_ptr_to_void_ptr)(void *in);
int pthread_create(..., void *ptr, void_ptr_to_void_ptr *fn);

the example should read:

typedef void *(*void_ptr_to_void_ptr)(void *in);
int pthread_create(..., void *ptr, void_ptr_to_void_ptr fn);

"void_ptr_to_void_ptr" is already typedef'd as a pointer to a function. So as written, the "pthread_create" declaration expects a pointer to a pointer to a function.

Note from the Author or Editor:
Fixed in repo by BK

Werner Wenzel  Feb 28, 2013  Jun 14, 2013
Printed
Page 191
In "Example 10-16", 1st line of 2nd paragraph of comment

Instead of:

Note that there is a \c error element ...

the second sentence should read:

Note that there is an \c error element ...

"\c" is a mere Doxygen format code which affects the appearance of the word "error" but does not itself show up in the documentation and the final wording should read "... an error ..."

Note from the Author or Editor:
Good point, thanks.



Fixed by BK.

Werner Wenzel  Feb 28, 2013  Jun 14, 2013
ePub
Page 195
Near the end of the section titled "Initiallize Arrays and Structs with Zeros"

I'm using an ePub version, so my page number is meaningless.

You tell us part way through this section that you can't initialize a variable-length array, and then present:


// A form for filling in from the end of an array. By the pick up
// where you left off rule, this will become {0.1, 0, 0, 0, 0, 1.1, 2.2}:
int len=7;
double list3[len] = {0.1, [len-2]=1.1, 2.2}

Regretfully, neither part of that works. It's gotta be:

double list3[7] = {0.1, [7-2]=1.1, 2.2}

Note from the Author or Editor:
Good point. This form usually appears when the length is a macro symbol, like #define len 7, making list3 a fixed-length array.

Fixed in the repo by BK., by merging this with the previous example.

Tyler Bindon  Sep 16, 2013 
PDF
Page 203
4th paragraph

A short function is presented. Then in the 4th paragraph the for-loop of this function is mentioned but instead of the '<=' comparison operator the character '&#8656;' is used.

Note from the Author or Editor:
fixed in the print edition.

Hector Zarate  Oct 05, 2012  Jan 18, 2013
Printed
Page 219
"mock-up of the process"

To me the entire mockup appears to be quite broken:

1) As written, the typedef's cannot work--ok, the code is incomplete ...

2) The "model_s" structure states a pointer to a function pointer instead of a mere function pointer which leads to an "'...estimate' is not a function" error.

3) The first arguments in the two function calls at the end of the mock-up state structures instead of pointers to structures which leads to "incompatible type for argument 1 of ?..._model.estimate? errors.

Here is a commented run-capable version of the mock-up:

/************ added ************/
typedef struct data_s {
int i;
} data_s;
/************ added ************/

/************ modified ************/
typedef struct model_s * (*data_to_estimated_model)(struct model_s *, struct data_s *);
/************ modified ************/

typedef struct model_s {
data_s *parameters, *data;
/* CORRECTED: "estimate" instead of "*estimate" */
/* avoids (later) "called object ?normal_model.estimate? is not a function" */
/* avoids (later) "called object ?zipf_model.estimate? is not a function" */
data_to_estimated_model estimate;
} model_s;

/************ added ************/
static model_s* model_copy(model_s *in){
static model_s out;
out = *in;
return &out;
}
/************ added ************/

//Takes in a copy of the input model with NULL parameters.
//Returns a copy of the input model with the parameters calculated.
static model_s* normal_est(model_s *in, data_s *d){
model_s *outmodel = model_copy(in);
//math goes here to calculate outmodel->parameters;
return outmodel;
}

static model_s* zipf_est(model_s *in, data_s *d){
model_s *outmodel = model_copy(in);
//entirely different math goes here to set outmodel->parameters;
return outmodel;
}

/************ added ************/
int main(void){
/************ added ************/

model_s normal_model = {.estimate = normal_est};
model_s zipf_model = {.estimate = zipf_est};

/************ replaced ************/
// data_s *d = text_to_data("infile");
/************ replaced ************/
/************ replacing ************/
data_s d = {42};
data_s *data = &d;
/************ replacing ************/

/* CORRECTED: "&normal_model" instead of "normal_model" */
/* avoids "error: incompatible type for argument 1 of ?normal_model.estimate?" */
model_s *norm_est = normal_model.estimate(&normal_model, data);
/* CORRECTED: "&zipf_model" instead of "zipf_model" */
/* avoids "error: incompatible type for argument 1 of ?zipf_model.estimate?" */
model_s *zipf_est = zipf_model.estimate(&zipf_model, data);

/************ added ************/
return 0;
}
/************ added ************/

Note from the Author or Editor:
Am learning a lesson here about sending _all_ sample code through a compiler.

Fixes:
--Removed * in what is now the "data_to_estimated_model estimate" line of the struct declaration.

--Changed "d" to "data" at callout 5.

--Changed normal_model & zipf_model from model_s to model_s*. I mention how it's better to always stick to pointer-to-structs or plain structs but not both, so I shouldn't mix them here.

--Thus, changed . to -> on the last two lines.


Fixed in the repo by BK.

Werner Wenzel  Mar 10, 2013  Jun 14, 2013
PDF
Page 221
first bullet point

"ar-guemnts" -> ar-guments (hyphen because of new line)

Note from the Author or Editor:
Fixed in the repository. Will appear online soon.

Robert H?ppner  Aug 24, 2012  Jan 18, 2013
Printed
Page 233
middle of 2nd par

"make use of the an 'easy' interface"

should be either "the" or "an", but not both

Note from the Author or Editor:
fixed in repo by BK.

Markus Wamser  May 22, 2013  Jun 14, 2013
Printed
Page 244
4th paragraph

Eignevector should be Eigenvector

Note from the Author or Editor:
fixed in repository.

David Stelpstra  Dec 30, 2012  Jan 18, 2013
PDF
Page 272
3rd paragraph

Where it says

"so that when we turn of the mutexes, there are more instructions that can trample each other."

the "turn of" should probably be "turn off"

Note from the Author or Editor:
Fixed in the repository. Will appear online soon.

Robert H?ppner  Aug 16, 2012  Jan 18, 2013