C Faq Programming
C Faq Programming
C Faq Programming
A:
A:
1.7:
A:
A:
1.30: What can I safely assume about the initial values of variables
which are not explicitly initialized? If global variables start
out as "zero," is that good enough for null pointers and
floating-point zeroes?
A:
struct x1 { ... };
typedef struct { ... } x2;
A:
2.2:
Why doesn't
struct x { ... };
x thestruct;
work?
A:
2.3:
A:
2.4:
A:
2.6:
A:
A:
2.8:
A:
A:
2.11:
A:
2.13: Why does sizeof report a larger size than I expect for a
structure type, as if there were padding at the end?
A:
A:
Section 3. Expressions
3.1:
a[i] = i++;
work?
A:
3.2:
A:
Although the postincrement and postdecrement operators ++ and -perform their operations after yielding the former value, the
implication of "after" is often misunderstood. It is *not*
guaranteed that an increment or decrement is performed
immediately after giving up the previous value and before any
other part of the expression is evaluated. It is merely
guaranteed that the update will be performed sometime before the
expression is considered "finished" (before the next "sequence
point," in ANSI C's terminology; see question 3.8). In the
example, the compiler chose to multiply the previous value by
itself and to perform both increments afterwards.
The behavior of code which contains multiple, ambiguous side
effects has always been undefined. (Loosely speaking, by
"multiple, ambiguous side effects" we mean any combination of
++, --, =, +=, -=, etc. in a single expression which causes the
same object either to be modified twice or modified and then
inspected. This is a rough definition; see question 3.8 for a
precise one, and question 11.33 for the meaning of "undefined.")
Don't even try to find out how your compiler implements such
things (contrary to the ill-advised exercises in many C
textbooks); as K&R wisely point out, "if you don't know *how*
they are done on various machines, that innocence may help to
protect you."
References: K&R1 Sec. 2.12 p. 50; K&R2 Sec. 2.12 p. 54; ANSI
Sec. 3.3; ISO Sec. 6.3; CT&P Sec. 3.7 p. 47; PCS Sec. 9.5 pp.
120-1.
3.3:
A:
3.4:
A:
Not in general.
Operator precedence and explicit parentheses impose only a
partial ordering on the evaluation of an expression. In the
expression
f() + g() * h()
although we know that the multiplication will happen before the
addition, there is no telling which of the three functions will
be called first.
When you need to ensure the order of subexpression evaluation,
you may need to use explicit temporary variables and separate
statements.
References: K&R1 Sec. 2.12 p. 49, Sec. A.7 p. 185; K&R2
A:
3.8:
A:
3.9:
So given
a[i] = i++;
we don't know which cell of a[] gets written to, but i does get
incremented by one.
A:
3.12: If I'm not using the value of the expression, should I use i++
or ++i to increment a variable?
A:
Since the two forms differ only in the value yielded, they are
entirely equivalent when only their side effect is needed.
See also question 3.3.
References: K&R1 Sec. 2.8 p. 43; K&R2 Sec. 2.8 p. 47; ANSI
Sec. 3.3.2.4, Sec. 3.3.3.1; ISO Sec. 6.3.2.4, Sec. 6.3.3.1; H&S
Sec. 7.4.4 pp. 192-3, Sec. 7.5.8 pp. 199-200.
Section 4. Pointers
4.2:
I'm trying to declare a pointer and allocate some space for it,
but it's not working. What's wrong with this code?
char *p;
*p = malloc(10);
A:
4.3:
A:
References: K&R1 Sec. 5.1 p. 91; K&R2 Sec. 5.1 p. 95; ANSI
Sec. 3.3.2, Sec. 3.3.3; ISO Sec. 6.3.2, Sec. 6.3.3; H&S
Sec. 7.4.4 pp. 192-3, Sec. 7.5 p. 193, Secs. 7.5.7,7.5.8 pp. 199200.
4.5:
A:
4.8:
int *ip;
f(ip);
the pointer in the caller remains unchanged.
A:
Are you sure the function initialized what you thought it did?
Remember that arguments in C are passed by value. The called
function altered only the passed copy of the pointer. You'll
either want to pass the address of the pointer (the function
will end up accepting a pointer-to-a-pointer), or have the
function return the pointer.
See also questions 4.9 and 4.11.
4.9:
A:
4.11:
A:
4.12: I've seen different methods used for calling functions via
pointers. What's the story?
A:
References: K&R1 Sec. 5.12 p. 116; K&R2 Sec. 5.11 p. 120; ANSI
Sec. 3.3.2.2; ISO Sec. 6.3.2.2; Rationale Sec. 3.3.2.2; H&S
Sec. 5.8 p. 147, Sec. 7.4.3 p. 190.
Section 5. Null Pointers
5.1:
A:
The language definition states that for each pointer type, there
is a special value -- the "null pointer" -- which is
distinguishable from all other pointer values and which is
"guaranteed to compare unequal to a pointer to any object or
function." That is, the address-of operator & will never yield
a null pointer, nor will a successful call to malloc().
(malloc() does return a null pointer when it fails, and this is
a typical use of null pointers: as a "special" pointer value
with some other meaning, usually "not allocated" or "not
pointing anywhere yet.")
A null pointer is conceptually different from an uninitialized
pointer. A null pointer is known not to point to any object or
function; an uninitialized pointer might point anywhere. See
also questions 1.30, 7.1, and 7.31.
As mentioned above, there is a null pointer for each pointer
type, and the internal values of null pointers for different
types may be different. Although programmers need not know the
internal values, the compiler must always be informed which type
of null pointer is required, so that it can make the distinction
if necessary (see questions 5.2, 5.5, and 5.6 below).
References: K&R1 Sec. 5.4 pp. 97-8; K&R2 Sec. 5.4 p. 102; ANSI
Sec. 3.2.2.3; ISO Sec. 6.2.2.3; Rationale Sec. 3.2.2.3; H&S
Sec. 5.3.2 pp. 121-3.
5.2:
A:
char *p = 0;
if(p != 0)
(See also question 5.3.)
However, an argument being passed to a function is not
necessarily recognizable as a pointer context, and the compiler
may not be able to tell that an unadorned 0 "means" a null
pointer. To generate a null pointer in a function call context,
an explicit cast may be required, to force the 0 to be
recognized as a pointer. For example, the Unix system call
execl takes a variable-length, null-pointer-terminated list of
character pointer arguments, and is correctly called like this:
execl("/bin/sh", "sh", "-c", "date", (char *)0);
If the (char *) cast on the last argument were omitted, the
compiler would not know to pass a null pointer, and would pass
an integer 0 instead. (Note that many Unix manuals get this
example wrong .)
When function prototypes are in scope, argument passing becomes
an "assignment context," and most casts may safely be omitted,
since the prototype tells the compiler that a pointer is
required, and of which type, enabling it to correctly convert an
unadorned 0. Function prototypes cannot provide the types for
variable arguments in variable-length argument lists however, so
explicit casts are still required for those arguments. (See
also question 15.3.) It is safest to properly cast all null
pointer constants in function calls: to guard against varargs
functions or those without prototypes, to allow interim use of
non-ANSI compilers, and to demonstrate that you know what you
are doing. (Incidentally, it's also a simpler rule to
remember.)
Summary:
Unadorned 0 okay:
initialization
function call,
no prototype in scope
assignment
comparison
function call,
variable argument in
varargs function call
prototype in scope,
fixed argument
References: K&R1 Sec. A7.7 p. 190, Sec. A7.14 p. 192; K&R2
Sec. A7.10 p. 207, Sec. A7.17 p. 209; ANSI Sec. 3.2.2.3; ISO
Sec. 6.2.2.3; H&S Sec. 4.6.3 p. 95, Sec. 6.2.7 p. 171.
5.3:
Is the abbreviated pointer comparison "if(p)" to test for nonnull pointers valid? What if the internal representation for
null pointers is nonzero?
A:
is equivalent to
if(p != 0)
(expr)?0:1
((expr) == 0)
if(p == 0)
A:
5.5:
A:
A:
5.9:
A:
No. (Using NULL may be preferable, but not for this reason.)
Although symbolic constants are often used in place of numbers
because the numbers might change, this is *not* the reason that
NULL is used in place of 0. Once again, the language guarantees
that source-code 0's (in pointer contexts) generate null
pointers. NULL is used only as a stylistic convention. See
questions 5.5 and 9.2.
2.
3.
4.
5.
The ASCII null character (NUL), which does have all bits
zero, but has no necessary relation to the null pointer
except in name; and...
6.
This article uses the phrase "null pointer" (in lower case) for
sense 1, the character "0" or the phrase "null pointer constant"
for sense 3, and the capitalized word "NULL" for sense 4.
5.14: Why is there so much confusion surrounding null pointers? Why
do these questions come up so often?
A:
2.
The Prime 50 series used segment 07777, offset 0 for the null
pointer, at least for PL/I. Later models used segment 0, offset
0 for null pointers in C, necessitating new instructions such as
TCNP (Test C Null Pointer), evidently as a sop to all the extant
poorly-written C code which made incorrect assumptions. Older,
word-addressed Prime machines were also notorious for requiring
larger byte pointers (char *'s) than word pointers (int *'s).
The Eclipse MV series from Data General has three
architecturally supported pointer formats (word, byte, and bit
pointers), two of which are used by C compilers: byte pointers
for char * and void *, and word pointers for everything else.
Some Honeywell-Bull mainframes use the bit pattern 06000 for
(internal) null pointers.
The CDC Cyber 180 Series has 48-bit pointers consisting of a
ring, segment, and offset. Most users (in ring 11) have null
pointers of 0xB00000000000. It was common on old CDC onescomplement machines to use an all-one-bits word as a special
flag for all kinds of data, including invalid addresses.
The old HP 3000 series uses a different addressing scheme for
byte addresses than for word addresses; like several of the
machines above it therefore uses different representations for
char * and void * pointers than for other pointers.
The Symbolics Lisp Machine, a tagged architecture, does not even
have conventional numeric pointers; it uses the pair
(basically a nonexistent handle) as a C null
pointer.
A:
The declaration extern char *a simply does not match the actual
definition. The type pointer-to-type-T is not the same as arrayof-type-T. Use extern char a[].
References: ANSI Sec. 3.5.4.2; ISO Sec. 6.5.4.2; CT&P Sec. 3.3
pp. 33-4, Sec. 4.5 pp. 64-5.
6.2:
A:
A:
A:
f(a)
char *a;
{ ... }
This conversion holds only within function formal parameter
declarations, nowhere else. If the conversion bothers you,
avoid it; many people have concluded that the confusion it
causes outweighs the small advantage of having the declaration
"look like" the call or the uses within the function.
See also question 6.21.
References: K&R1 Sec. 5.3 p. 95, Sec. A10.1 p. 205; K&R2
Sec. 5.3 p. 100, Sec. A8.6.3 p. 218, Sec. A10.1 p. 226; ANSI
Sec. 3.5.4.3, Sec. 3.7.1, Sec. 3.9.6; ISO Sec. 6.5.4.3,
Sec. 6.7.1, Sec. 6.9.6; H&S Sec. 9.3 p. 271; CT&P Sec. 3.3 pp.
33-4.
6.7:
A:
6.8:
A:
6.9:
pointers.
A:
6.11:
A:
The type.
In Standard C, &arr yields a pointer, of type pointer-to-arrayof-T, to the entire array. (In pre-ANSI C, the & in &arr
generally elicited a warning, and was generally ignored.) Under
all C compilers, a simple reference (without an explicit &) to
an array yields a pointer, of type pointer-to-T, to the array's
first element. (See also questions 6.3, 6.13, and 6.18.)
References: ANSI Sec. 3.2.2.1, Sec. 3.3.3.2; ISO Sec. 6.2.2.1,
Sec. 6.3.3.2; Rationale Sec. 3.3.3.2; H&S Sec. 7.5.6 p. 198.
The rule (see question 6.3) by which arrays decay into pointers
is not applied recursively. An array of arrays (i.e. a twodimensional array in C) decays into a pointer to an array, not a
pointer to a pointer. Pointers to arrays can be confusing, and
must be treated carefully; see also question 6.13. (The
confusion is heightened by the existence of incorrect compilers,
including some old versions of pcc and pcc-derived lints, which
improperly accept assignments of multi-dimensional arrays to
multi-level pointers.)
This function could be called with the array from question 6.18
as
f2(&array[0][0], NROWS, NCOLUMNS);
It must be noted, however, that a program which performs
multidimensional array subscripting "by hand" in this way is not
in strict conformance with the ANSI C Standard; according to an
official interpretation, the behavior of accessing
(&array[0][0])[x] is not defined for x >= NCOLUMNS.
gcc allows local arrays to be declared having sizes which are
specified by a function's arguments, but this is a nonstandard
extension.
When you want to be able to use a function on multidimensional
arrays of various sizes, one solution is to simulate all the
arrays dynamically, as in question 6.16.
See also questions 6.18, 6.20, and 6.15.
References: ANSI Sec. 3.3.6; ISO Sec. 6.3.6.
6.20: How can I use statically- and dynamically-allocated
multidimensional arrays interchangeably when passing them to
functions?
A:
7.1:
A:
7.2:
A:
But the man page for strcat() says that it takes two char *'s as
arguments. How am I supposed to know to allocate things?
A:
7.5:
A:
/* WRONG */
/* WRONG */
A:
7.7:
Why does some code carefully cast the values returned by malloc
to the pointer type being allocated?
A:
7.8:
strcpy(p, s);
Shouldn't that be malloc((strlen(s) + 1) * sizeof(char))?
A:
7.14: I've heard that some operating systems don't actually allocate
malloc'ed memory until the program tries to use it. Is this
legal?
A:
It's hard to say. The Standard doesn't say that systems can act
this way, but it doesn't explicitly say that they can't, either.
References: ANSI Sec. 4.10.3; ISO Sec. 7.10.3.
7.16: I'm allocating a large array for some numeric work, using the
line
double *array = malloc(256 * 256 * sizeof(double));
malloc() isn't returning null, but the program is acting
strangely, as if it's overwriting memory, or malloc() isn't
allocating as much as I asked for, or something.
A:
Notice that 256 x 256 is 65,536, which will not fit in a 16-bit
int, even before you multiply it by sizeof(double). If you need
to allocate this much memory, you'll have to be careful. If
size_t (the type accepted by malloc()) is a 32-bit type on your
machine, but int is 16 bits, you might be able to get away with
writing 256 * (256 * sizeof(double)) (see question 3.14).
Otherwise, you'll have to break your data structure up into
smaller chunks, or use a 32-bit machine, or use some nonstandard
memory allocation routines. See also question 19.23.
7.17: I've got 8 meg of memory in my PC. Why can I only seem to
malloc() 640K or so?
A:
7.20: You can't use dynamically-allocated memory after you free it,
can you?
A:
A:
7.27: So can I query the malloc package to find out how big an
allocated block is?
A:
Not portably.
Why doesn't
strcat(string, '!');
work?
A:
a ! to a string, use
strcat(string, "!");
See also questions 1.32, 7.2, and 16.6.
References: CT&P Sec. 1.5 pp. 9-10.
8.2:
A:
8.3:
If I can say
char a[] = "Hello, world!";
why can't I say
char a[14];
a = "Hello, world!";
A:
Strings are arrays, and you can't assign arrays directly. Use
strcpy() instead:
A:
8.9:
A:
A:
#define YES 1
#define NO 0
enum bool {no, yes};
A:
References: K&R1 Sec. 2.6 p. 39, Sec. 2.7 p. 41; K&R2 Sec. 2.6
p. 42, Sec. 2.7 p. 44, Sec. A7.4.7 p. 204, Sec. A7.9 p. 206;
ANSI Sec. 3.3.3.3, Sec. 3.3.8, Sec. 3.3.9, Sec. 3.3.13,
Sec. 3.3.14, Sec. 3.3.15, Sec. 3.6.4.1, Sec. 3.6.5; ISO
Sec. 6.3.3.3, Sec. 6.3.8, Sec. 6.3.9, Sec. 6.3.13, Sec. 6.3.14,
Sec. 6.3.15, Sec. 6.6.4.1, Sec. 6.6.5; H&S Sec. 7.5.4 pp. 196-7,
Sec. 7.6.4 pp. 207-8, Sec. 7.6.5 pp. 208-9, Sec. 7.7 pp. 217-8,
Sec. 7.8 pp. 218-9, Sec. 8.5 pp. 238-9, Sec. 8.6 pp. 241-4;
"What the Tortoise Said to Achilles".
9.3:
A:
A:
10.6: I'm splitting up a program into multiple source files for the
first time, and I'm wondering what to put in .c files and what
to put in .h files. (What does ".h" mean, anyway?)
A:
Typically, headers named with <> syntax are searched for in one
or more standard places. Header files named with "" syntax are
first searched for in the "current directory," then (if not
found) in the same standard places.
Traditionally (especially under Unix compilers), the current
directory is taken to be the directory containing the file
containing the #include directive. Under other compilers,
however, the current directory (if any) is the directory in
which the compiler was initially invoked. Check your compiler
documentation.
References: K&R2 Sec. A12.4 p. 231; ANSI Sec. 3.8.2; ISO
Sec. 6.8.2; H&S Sec. 3.4 p. 55.
10.9: I'm getting strange syntax errors on the very first declaration
in a file, but it looks fine.
A:
A:
10.18: I inherited some code which contains far too many #ifdef's for
my taste. How can I preprocess the code to leave only one
conditional compilation set, without running it through the
preprocessor and expanding all of the #include's and #define's
as well?
A:
10.20: I have some old code that tries to construct identifiers with a
macro like
#define Paste(a, b) a/**/b
but it doesn't work any more.
A:
A:
10.23: How can I use a macro argument inside a string literal in the
macro expansion?
A:
DEBUG("i = %d" _ i)
It is often better to use a bona-fide function, which can take a
variable number of arguments in a well-defined way. See
questions 15.4 and 15.5.
Section 11. ANSI/ISO Standard C
11.1:
A:
11.2:
A:
A:
A:
11.5:
A:
A:
11.9:
A:
You can use a pointer-to-T (for any type T) where a pointer-toconst-T is expected. However, the rule (an explicit exception)
which permits slight mismatches in qualified pointer types is
not applied recursively, but only at the top level.
You must use explicit casts (e.g. (const char **) in this case)
when assigning (or passing) pointers which have qualifier
11.14: I believe that declaring void main() can't fail, since I'm
calling exit() instead of returning, and anyway my operating
system ignores a program's exit/return status.
A:
Yes and no. The Standard says that they are equivalent.
However, a few older, nonconforming systems may have problems
with one or the other form. Also, a return from main() cannot
be expected to work if data local to main() might be needed
during cleanup; see also question 16.4. (Finally, the two forms
are obviously not equivalent in a recursive call to main().)
References: K&R2 Sec. 7.6 pp. 163-4; ANSI Sec. 2.1.2.2.3; ISO
Sec. 5.1.2.2.3.
11.19: I'm getting strange syntax errors inside lines I've #ifdeffed
out.
A:
11.21: What does "#pragma once" mean? I found it in some header files.
A:
A:
11.27: Why does the ANSI Standard not guarantee more than six caseinsensitive characters of external identifier significance?
A:
A:
12.5: How can I read one character at a time, without waiting for the
RETURN key?
A:
12.9: Someone told me it was wrong to use %lf with printf(). How can
printf() use %f for type double, if scanf() requires %lf?
A:
It's true that printf's %f specifier works with both float and
double arguments. Due to the "default argument promotions"
(which apply in variable-length argument lists such as
printf's, whether or not prototypes are in scope), values of
type float are promoted to double, and printf() therefore sees
only doubles. See also questions 12.13 and 15.2.
References: K&R1 Sec. 7.3 pp. 145-47, Sec. 7.4 pp. 147-50; K&R2
Sec. 7.2 pp. 153-44, Sec. 7.4 pp. 157-59; ANSI Sec. 4.9.6.1,
Sec. 4.9.6.2; ISO Sec. 7.9.6.1, Sec. 7.9.6.2; H&S Sec. 15.8 pp.
357-64, Sec. 15.11 pp. 366-78; CT&P Sec. A.1 pp. 121-33.
12.10: How can I implement a variable field width with printf? That
is, instead of %8d, I want the width to be specified at run
time.
A:
12.11: How can I print numbers with commas separating the thousands?
What about currency formatted numbers?
A:
Unlike printf(), scanf() uses %lf for values of type double, and
%f for float. See also question 12.9.
12.17: When I read numbers from the keyboard with scanf "%d\n", it
seems to hang until I type one extra line of input.
A:
12.18: I'm reading a number with scanf %d and then a string with
gets(), but the compiler seems to be skipping the call to
gets()!
A:
12.20: Why does everyone say not to use scanf()? What should I use
instead?
A:
12.26: How can I flush pending input so that a user's typeahead isn't
12.30: I'm trying to update a file in place, by using fopen mode "r+",
reading a certain string, and writing back a modified string,
but it's not working.
A:
Be sure to call fseek before you write, both to seek back to the
beginning of the string you're trying to overwrite, and because
an fseek or fflush is always required between reading and
writing in the read/write "+" modes. Also, remember that you
can only overwrite characters with the same number of
replacement characters; see also question 19.14.
References: ANSI Sec. 4.9.5.3; ISO Sec. 7.9.5.3.
12.34: Once I've used freopen(), how can I get the original stdout (or
stdin) back?
A:
There isn't a good way. If you need to switch back, the best
solution is not to have used freopen() in the first place. Try
using your own explicit output (or input) stream variable, which
you can reassign at will, while leaving the original stdout (or
stdin) undisturbed.
12.38: How can I read a binary data file properly? I'm occasionally
seeing 0x0a and 0x0d values getting garbled, and it seems to hit
EOF prematurely if the data contains the value 0x1a.
A:
When you're reading a binary data file, you should specify "rb"
mode when calling fopen(), to make sure that text file
translations do not occur. Similarly, when writing binary data
files, use "wb".
Note that the text/binary distinction is made when you open the
file: once a file is open, it doesn't matter which I/O calls you
use on it. See also question 20.5.
References: ANSI Sec. 4.9.5.3; ISO Sec. 7.9.5.3; H&S Sec. 15.2.1
p. 348.
13.2: Why does strncpy() not always place a '\0' terminator in the
destination string?
A:
look like
int mystructcmp(const void *p1, const void *p2)
{
const struct mystruct *sp1 = p1;
const struct mystruct *sp2 = p2;
/* now compare sp1->whatever and sp2-> ... */
(The conversions from generic pointers to struct mystruct
pointers happen in the initializations sp1 = p1 and sp2 = p2;
the compiler performs the conversions implicitly since p1 and p2
are void pointers. Explicit casts, and char * pointers, would
be required under a pre-ANSI compiler. See also question 7.7.)
If, on the other hand, you're sorting pointers to structures,
you'll need indirection, as in question 13.8:
sp1 = *(struct mystruct **)p1 .
In general, it is a bad idea to insert casts just to "shut the
compiler up." Compiler warnings are usually trying to tell you
something, and unless you really know what you're doing, you
ignore or muzzle them at your peril. See also question 4.9.
References: ANSI Sec. 4.10.5.2; ISO Sec. 7.10.5.2; H&S Sec. 20.5
p. 419.
13.10: How can I sort a linked list?
A:
13.11: How can I sort more data than will fit in memory?
A:
You want an "external sort," which you can read about in Knuth,
Volume 3. The basic idea is to sort the data in chunks (as much
as will fit in memory at one time), write each sorted chunk to a
temporary file, and then merge the files. Your operating system
may provide a general-purpose sort utility, and if so, you can
13.14: How can I add N days to a date? How can I find the difference
/* POOR */
other ideas.
References: Knuth Sec. 3.4.1 p. 117; Box and Muller, "A Note on
the Generation of Random Normal Deviates"; Press et al.,
_Numerical Recipes in C_ Sec. 7.2 pp. 288-290.
13.24: I'm trying to port this
A: Those routines are variously
old program. Why do I
obsolete; you should
get "undefined external"
instead:
errors for:
index?
rindex?
bcopy?
bcmp?
bzero?
use strchr.
use strrchr.
use memmove, after
interchanging the first and
second arguments (see also
question 11.25).
use memcmp.
use memset, with a second
argument of 0.
Many linkers make one pass over the list of object files and
libraries you specify, and extract from libraries only those
modules which satisfy references which have so far come up as
undefined. Therefore, the order in which libraries are listed
with respect to object files (and each other) is significant;
usually, you want to search the libraries last. (For example,
under Unix, put any -l options towards the end of the command
That message is a quirk of the old Unix linkers. You only get
an error about _end being undefined when other things are
undefined, too -- fix the others, and the error about _end will
disappear. (See also questions 13.25 and 13.26.)
14.2: I'm trying to take some square roots, but I'm getting crazy
numbers.
A:
Make sure you're actually linking with the math library. For
instance, under Unix, you usually need to use the -lm option, at
the *end* of the command line, when compiling/linking. See also
questions 13.25 and 13.26.
A:
/* WRONG */
#include
if(fabs(a - b) <= epsilon * a)
for some suitably-chosen epsilon.
References: Knuth Sec. 4.2.2 pp. 217-8.
14.6: How do I round numbers?
A:
14.9: How do I test for IEEE NaN and other special values?
A:
14.13: I'm having trouble with a Turbo C program which crashes and says
something like "floating point formats not linked."
A:
/* +1 for trailing \0 */
if(retbuf == NULL)
return NULL;
/* error */
(void)strcpy(retbuf, first);
va_start(argp, first);
}
Usage is something like
char *str = vstrcat("Hello, ", "world!", (char *)NULL);
Note the cast on the last argument; see questions 5.2 and 15.3.
(Also note that the caller must free the returned, malloc'ed
storage.)
Under a pre-ANSI compiler, rewrite the function definition
without a prototype ("char *vstrcat(first) char *first; {"),
include rather than , add "extern
char *malloc();", and use int instead of size_t. You may also
have to delete the (void) casts, and use the older varargs
package instead of stdarg. See also question 15.7.
References: K&R2 Sec. 7.3 p. 155, Sec. B7 p. 254; ANSI Sec. 4.8;
ISO Sec. 7.8; Rationale Sec. 4.8; H&S Sec. 11.4 pp. 296-9; CT&P
Sec. A.3 pp. 139-141; PCS Sec. 11 pp. 184-5, Sec. 13 p. 242.
15.5: How can I write a function that takes a format string and a
variable number of arguments, like printf(), and passes them to
printf() to do most of the work?
A:
15.8: How can I discover how many arguments a function was actually
called with?
A:
15.13: How can I call a function with an argument list built up at run
time?
A:
16.5: This program runs perfectly on one machine, but I get weird
results on another. Stranger still, adding or removing
debugging printouts changes the symptoms...
A:
Lots of things could be going wrong; here are a few of the more
common things to check:
uninitialized local variables (see also question 7.1)
integer overflow, especially on 16-bit machines,
especially of an intermediate result when doing things
like a * b / c (see also question 3.14)
undefined evaluation order (see questions 3.1 through 3.4)
omitted declaration of external functions, especially
those which return something other than int
(see questions 1.25 and 14.2)
31-2.
16.8: What do "Segmentation violation" and "Bus error" mean?
A:
K&R, while providing the example most often copied, also supply
a good excuse for disregarding it:
The position of braces is less important,
although people hold passionate beliefs.
We have chosen one of several popular styles.
Pick a style that suits you, then use it
consistently.
It is more important that the layout chosen be consistent (with
itself, and with nearby or common code) than that it be
"perfect." If your coding environment (i.e. local custom or
company policy) does not suggest a style, and you don't feel
like inventing your own, just copy K&R. (The tradeoffs between
various indenting and brace placement options can be
exhaustively and minutely examined, but don't warrant repetition
here. See also the Indian Hill Style Guide.)
The elusive quality of "good style" involves much more than mere
code layout details; don't spend time on formatting to the
exclusion of more substantive code quality issues.
See also question 10.6.
References: K&R1 Sec. 1.2 p. 10; K&R2 Sec. 1.2 p. 10.
17.3: Here's a neat trick for checking whether two strings are equal:
if(!strcmp(s1, s2))
Is this good style?
A:
17.5: I came across some code that puts a (void) cast before each call
to printf(). Why?
A:
17.9: Where can I get the "Indian Hill Style Guide" and other coding
standards?
A:
File or directory:
cs.washington.edu
pub/cstyle.tar.Z
(the updated Indian Hill guide)
ftp.cs.toronto.edu
doc/programming
(including Henry Spencer's
"10 Commandments for C Programmers")
ftp.cs.umd.edu
pub/style-guide
a C cross-reference
generator
a C beautifier/prettyprinter
a revision control or
configuration management
tool
RCS or SCCS
a C source obfuscator
(shrouder)
a "make" dependency
generator
makedepend, or try cc -M or
cpp -M
a C lines-of-source
counter
a prototype generator
a "selective" C
preprocessor
language translation
tools
C verifiers (lint)
a C compiler!
See if you can run lint first (perhaps with the -a, -c, -h, -p
or other options). Many C compilers are really only halfcompilers, electing not to diagnose numerous source code
difficulties which would not actively preclude code generation.
See also questions 16.5 and 16.8.
References: Ian Darwin, _Checking C Programs with lint_ .
18.5: How can I shut off the "warning: possible pointer alignment
problem" message which lint gives me for each call to malloc()?
A:
There are far too many books on C to list here; it's impossible
to rate them all. Many people believe that the best one was
also the first: _The C Programming Language_, by Kernighan and
Ritchie ("K&R," now in its second edition). Opinions vary on
K&R's suitability as an initial programming text: many of us did
learn C from it, and learned it well; some, however, feel that
it is a bit too clinical as a first tutorial for those without
much programming background.
An excellent reference manual is _C: A Reference Manual_, by
Samuel P. Harbison and Guy L. Steele, now in its fourth edition.
Though not suitable for learning C from scratch, this FAQ list
has been published in book form; see the Bibliography.
Mitch Wright maintains an annotated bibliography of C and Unix
books; it is available for anonymous ftp from ftp.rahul.net in
directory pub/mitch/YABL/.
This FAQ list's editor maintains a collection of previous
answers to this question, which is available upon request. See
also question 18.9 above.
information). The FSF's GNU C (gcc) distribution includes a ctorture-test which checks a number of common problems with
compilers. Kahan's paranoia test, found in netlib/paranoia on
netlib.att.com, strenuously tests a C implementation's floating
point capabilities.
18.16: Where and how can I get copies of all these freely distributable
programs?
A:
Once upon a time, Unix had a fairly nice little set of deviceindependent plot routines described in plot(3) and plot(5), but
they've largely fallen into disuse.
If you're programming for MS-DOS, you'll probably want to use
libraries conforming to the VESA or BGI standards.
If you're trying to talk to a particular plotter, making it draw
is usually a matter of sending it the appropriate escape
sequences; see also question 19.9. The vendor may supply a Ccallable library, or you may be able to find one on the net.
If you're programming for a particular window system (Macintosh,
X windows, Microsoft Windows), you will use its facilities; see
the relevant documentation or newsgroup or FAQ list.
References: PCS Sec. 5.4 pp. 75-77.
19.11: How can I check whether a file exists? I want to warn the user
19.12: How can I find out the size of a file, prior to reading it in?
A:
19.14: How can I insert or delete a line (or record) in the middle of a
file?
A:
19.15: How can I recover the file name given an open stream or file
descriptor?
A:
19.17: Why can't I open a file by its explicit path? The call
fopen("c:\newdir\file.dat", "r")
is failing.
A:
19.18: I'm getting an error, "Too many open files". How can I increase
the allowable number of simultaneously open files?
A:
See if you can use the opendir() and readdir() routines, which
are part of the POSIX standard and are available on most Unix
variants. Implementations also exist for MS-DOS, VMS, and other
systems. (MS-DOS also has FINDFIRST and FINDNEXT routines which
do essentially the same thing.) readdir() only returns file
names; if you need more information about the file, try calling
stat(). To match filenames to some wildcard pattern, see
question 13.7.
References: K&R2 Sec. 8.6 pp. 179-184; PCS Sec. 13 pp. 230-1;
POSIX Sec. 5.1; Schumacher, ed., _Software Solutions in C_
Sec. 8.
19.22: How can I find out how much memory is available?
A:
19.24: What does the error message "DGROUP data allocation exceeds 64K"
mean, and what can I do about it? I thought that using large
model meant that I could use more than 64K of data!
A:
19.30: How can I invoke another program or command and trap its output?
A:
If you can't use popen(), you may be able to use system(), with
the output going to a file which you then open and read.
If you're using Unix and popen() isn't sufficient, you can learn
about pipe(), dup(), fork(), and exec().
(One thing that probably would *not* work, by the way, would be
to use freopen().)
References: PCS Sec. 11 p. 169.
19.31: How can my program discover the complete pathname to the
executable from which it was invoked?
A:
It's hard; see also question 19.31 above. Even if you can
figure out a workable way to do it, you might want to consider
making the program's auxiliary (library) directory configurable,
perhaps with an environment variable. (It's especially
important to allow variable placement of a program's
configuration files when the program will be used by several
people, e.g. on a multiuser system.)
process.
19.36: How can I read in an object file and jump to routines in it?
A:
19.37: How can I implement a delay, or time a user's response, with subsecond resolution?
A:
long int i;
for(i = 0; i < 1000000; i++)
;
but resist this temptation if at all possible! For one thing,
your carefully-calculated delay loops will stop working next
month when a faster processor comes out. Perhaps worse, a
clever compiler may notice that the loop does nothing and
optimize it away completely.
References: H&S Sec. 18.1 pp. 398-9; PCS Sec. 12 pp. 197-8,2156; POSIX Sec. 4.5.2.
19.38: How can I trap or ignore keyboard interrupts like control-C?
A:
are being called (and *whether* any input routines are active at
all). On MS-DOS systems, setcbrk() or ctrlbrk() functions may
also be involved.
References: ANSI Secs. 4.7,4.7.1; ISO Secs. 7.7,7.7.1; H&S
Sec. 19.6 pp. 411-3; PCS Sec. 12 pp. 210-2; POSIX
Secs. 3.3.1,3.3.4.
19.39: How can I handle floating-point exceptions gracefully?
A:
All of these questions are outside of the scope of this list and
have much more to do with the networking facilities which you
have available than they do with C. Good books on the subject
are Douglas Comer's three-volume _Internetworking with TCP/IP_
and W. R. Stevens's _UNIX Network Programming_. (There is also
plenty of information out on the net itself.)
19.40b: How do I use BIOS calls? How can I write ISR's? How can I
create TSR's?
A:
20.5: How can I write data files which can be read on other machines
with different word size, byte order, or floating point formats?
A:
A:
/* for CHAR_BIT */
Make sure you really know what you're asking. Integers are
stored internally in binary, although for most purposes it is
not incorrect to think of them as being in octal, decimal, or
hexadecimal, whichever is convenient. The base in which a
number is expressed matters only when that number is read in
from or written out to the outside world.
In source code, a non-decimal base is indicated by a leading 0
or 0x (for octal or hexadecimal, respectively). During I/O, the
base of a formatted number is controlled in the printf and scanf
family of functions by the choice of format specifier (%d, %o,
%x, etc.) and in the strtol() and strtoul() functions by the
third argument. During *binary* I/O, however, the base again
becomes immaterial.
For more information about "binary" I/O, see question 2.11. See
also questions 8.6 and 13.1.
References: ANSI Secs. 4.10.1.5,4.10.1.6; ISO
Secs. 7.10.1.5,7.10.1.6.
20.12: What is the most efficient way to count the number of bits which
are set in a value?
A:
Yes.
Long ago, in the early days of C, they were required, and just
enough people learned C then, and wrote code which is still in
circulation, that the notion that they might still be required
is widespread.
(As it happens, parentheses are optional with the sizeof
20.25: How can I call FORTRAN (C++, BASIC, Pascal, Ada, LISP) functions
from C? (And vice versa?)
A:
ptoc
f2c
C++ was derived from C, and is largely based on it, but there
are some legal C constructs which are not legal C++.
Conversely, ANSI C inherited several features from C++,
including prototypes and const, so neither language is really a
subset or superset of the other. In spite of the differences,
many C programs will compile correctly in a C++ environment, and
many recent compilers offer both C and C++ compilation modes.
References: H&S p. xviii, Sec. 1.1.5 p. 6, Sec. 2.8 pp. 36-7,
Sec. 4.9 pp. 104-107.
20.31: How can I find the day of the week given the date?
A:
Yes and no, respectively. The full expression for the present
Gregorian calendar is
year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)
See a good astronomical almanac or other reference for details.
(To forestall an eternal debate: references which claim the
existence of a 4000-year rule are wrong.)
20.34: Here's a good puzzle: how do you write a program which produces
its own source code as its output?
A:
{apple,pyramid,sun,uunet}!hoptoad!judges or
[email protected]
(Note that these are *not* the addresses for submitting
entries.)
Contest winners should be announced at the winter USENIX
conference in January, and are posted to the net sometime
thereafter. Winning entries from previous years (back to 1984)
are archived at ftp.uu.net (see question 18.16) under the
directory pub/ioccc/.
As a last resort, previous winners may be obtained by sending email to the above address, using the Subject: "send YEAR
winners", where YEAR is a single four-digit year, a year range,
or "all".
20.37: What was the entry keyword mentioned in K&R1?
A:
20.40: Where can I get extra copies of this list? What about back
issues?
A: