C Programming FAQs
C Programming FAQs
Certain topics come up again and again on this newsgroup. They are good
questions, and the answers may not be immediately obvious, but each time
they recur, much net bandwidth and reader time is wasted on repetitive
responses, and on tedious corrections to the incorrect answers which are
inevitably posted.
This article was last modified on September 5, 1996, and its travels
may have taken it far from its original home on Usenet. It may now
be out-of-date, particularly if you are looking at a printed copy or one
retrieved from a tertiary archive site or CD-ROM. You should be able to
obtain the most up-to-date copy by anonymous ftp from sites
ftp.eskimo.com,
rtfm.mit.edu, or ftp.uu.net (see questions 18.16 and 20.40), or by
sending the e-mail message "help" to mail-server@rtfm.mit.edu . Since
this list is modified from time to time, its question numbers may not
match those in older or newer copies which are in circulation; be
careful when referring to FAQ list entries by number alone.
This article was produced for free redistribution. You should not need
to pay anyone for a copy of it.
(The question numbers within each section are not always continuous,
because they are aligned with the aforementioned book-length version,
which contains even more questions.)
References: K&R1 Sec. 2.2 p. 34; K&R2 Sec. 2.2 p. 36, Sec. A4.2
pp. 195-6, Sec. B11 p. 257; ANSI Sec. 2.2.4.2.1, Sec. 3.1.2.5;
ISO Sec. 5.2.4.2.1, Sec. 6.1.2.5; H&S Secs. 5.1,5.2 pp. 110-114.
1.4: What should the 64-bit type on new, 64-bit machines be?
1.7: What's the best way to declare and define global variables?
need only be entered once in one header file, and turned into a
definition or a declaration depending on the setting of some
macro, but it's not clear if this is worth the trouble.
References: K&R1 Sec. 4.5 pp. 76-7; K&R2 Sec. 4.4 pp. 80-1; ANSI
Sec. 3.1.2.2, Sec. 3.7, Sec. 3.7.2, Sec. F.5.11; ISO
Sec. 6.1.2.2, Sec. 6.7, Sec. 6.7.2, Sec. G.5.11; Rationale
Sec. 3.1.2.2; H&S Sec. 4.8 pp. 101-104, Sec. 9.2.3 p. 267; CT&P
Sec. 4.2 pp. 54-56.
and
int f();
typedef struct {
char *item;
NODEPTR next;
} *NODEPTR;
struct node {
char *item;
struct node *next;
};
References: K&R1 Sec. 6.5 p. 101; K&R2 Sec. 6.5 p. 139; ANSI
Sec. 3.5.2, Sec. 3.5.2.3, esp. examples; ISO Sec. 6.5.2,
Sec. 6.5.2.3; H&S Sec. 5.6.1 pp. 132-3.
1. char *(*(*a[N])())();
3. Use the cdecl program, which turns English into C and vice
versa:
References: K&R1 Sec. 4.2 p. 70; K&R2 Sec. 4.2 p. 72; ANSI
Sec. 3.3.2.2; ISO Sec. 6.3.2.2; H&S Sec. 4.7 p. 101.
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?
References: K&R1 Sec. 4.9 pp. 82-4; K&R2 Sec. 4.9 pp. 85-86;
ANSI Sec. 3.5.7, Sec. 4.10.3.1, Sec. 4.10.5.3; ISO Sec. 6.5.7,
Sec. 7.10.3.1, Sec. 7.10.5.3; H&S Sec. 4.2.8 pp. 72-3, Sec. 4.6
pp. 92-3, Sec. 4.6.2 pp. 94-5, Sec. 4.6.3 p. 96, Sec. 16.1 p.
386.
f()
{
char a[] = "Hello, world!";
}
char *p = malloc(10);
References: K&R2 Sec. 5.5 p. 104; ANSI Sec. 3.1.4, Sec. 3.5.7;
ISO Sec. 6.1.4, Sec. 6.5.7; Rationale Sec. 3.1.4; H&S Sec. 2.7.4
pp. 31-2.
struct x1 { ... };
typedef struct { ... } x2;
struct x { ... };
x thestruct;
work?
2.4: What's the best way of implementing opaque (abstract) data types
in C?
struct name {
int namelen;
char namestr[1];
};
and then did some tricky allocation to make the namestr array
act like it had several elements. Is this legal or portable?
...
char namestr[MAXSIZE];
...
References: K&R1 Sec. 6.2 p. 121; K&R2 Sec. 6.2 p. 129; ANSI
Sec. 3.1.2.5, Sec. 3.2.2.1, Sec. 3.3.16; ISO Sec. 6.1.2.5,
Sec. 6.2.2.1, Sec. 6.3.16; H&S Sec. 5.6.2 p. 133.
2.13: Why does sizeof report a larger size than I expect for a
structure type, as if there were padding at the end?
offsetb = offsetof(struct a, b)
struct list {
char *item;
struct list *next;
}
main(argc, argv)
{ ... }
References: K&R2 Sec. 6.8 pp. 148-9; ANSI Sec. 3.5.7; ISO
Sec. 6.5.7; H&S Sec. 4.6.7 p. 100.
Section 3. Expressions
a[i] = i++;
work?
References: K&R1 Sec. 2.12; K&R2 Sec. 2.12; ANSI Sec. 3.3; ISO
Sec. 6.3.
int i = 7;
printf("%d\n", i++ * i++);
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.
int i = 3;
i = i++;
A: Not in general.
References: K&R1 Sec. 2.6 p. 38, Secs. A7.11-12 pp. 190-1; K&R2
Sec. 2.6 p. 41, Secs. A7.14-15 pp. 207-8; ANSI Sec. 3.3.13,
Sec. 3.3.14, Sec. 3.3.15; ISO Sec. 6.3.13, Sec. 6.3.14,
Sec. 6.3.15; H&S Sec. 7.7 pp. 217-8, Sec. 7.8 pp. 218-20,
Sec. 7.12.1 p. 229; CT&P Sec. 3.7 pp. 46-7.
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, right?
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.
(However, the prefix form is preferred in C++.)
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.
work?
Note that (long int)(a * b) would *not* have the desired effect.
A similar problem can arise when two integers are divided, with
the result assigned to a floating-point variable.
References: K&R1 Sec. 2.7 p. 41; K&R2 Sec. 2.7 p. 44; ANSI
Sec. 3.2.1.5; ISO Sec. 6.2.1.5; H&S Sec. 6.3.4 p. 176; CT&P
Sec. 3.9 pp. 49-50.
((condition) ? a : b) = complicated_expression;
References: ANSI Sec. 3.3.15 esp. footnote 50; ISO Sec. 6.3.15;
H&S Sec. 7.1 pp. 179-180.
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);
p = malloc(10);
It's when you're manipulating the pointed-to memory that you use
* as an indirection operator:
*p = 'H';
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.
199-
200.
4.5: I have a char * pointer that happens to point to some ints, and
I want to step it over them. Why doesn't
((int *)p)++;
work?
p += sizeof(int);
void f(ip)
int *ip;
{
static int dummy = 5;
ip = &dummy;
}
int *ip;
f(ip);
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.
f(&5);
int five = 5;
f(&five);
References: K&R1 Sec. 1.8 pp. 24-5, Sec. 5.2 pp. 91-3; K&R2
Sec. 1.8 pp. 27-8, Sec. 5.2 pp. 91-3; ANSI Sec. 3.3.2.2, esp.
footnote 39; ISO Sec. 6.3.2.2; H&S Sec. 9.5 pp. 273-4.
4.12: I've seen different methods used for calling functions via
pointers. What's the story?
r = fp();
is legal and works correctly, whether fp is the name of a
function or a pointer to one. (The usage has always been
unambiguous; there is nothing you ever could have done with a
function pointer followed by an argument list except call the
function pointed to.) An explicit * is still allowed (and
recommended, if portability to older compilers is important).
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.
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.")
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.
char *p = 0;
if(p != 0)
Summary:
function call,
prototype in scope,
fixed argument
if(expr)
if((expr) != 0)
References: K&R1 Sec. 5.4 pp. 97-8; K&R2 Sec. 5.4 p. 102; ANSI
Sec. 4.1.5, Sec. 3.2.2.3; ISO Sec. 7.1.6, Sec. 6.2.2.3;
Rationale Sec. 4.1.5; H&S Sec. 5.3.2 p. 122, Sec. 11.1 p. 292.
5.5: How should NULL be defined on a machine which uses a nonzero bit
pattern as the internal representation of a null pointer?
could fail.
if you must.
References: K&R1 Sec. 5.4 pp. 97-8; K&R2 Sec. 5.4 p. 102.
5.10: But wouldn't it be better to use NULL (rather than 0), in case
the value of NULL changes, perhaps on a machine with nonzero
internal null pointers?
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.
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...
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.15: I'm confused. I just can't understand all this null pointer
stuff.
5.17: Seriously, have any actual machines really used nonzero null
pointers, or different representations for pointers to different
types?
A: 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).
5.20: What does a run-time "null pointer assignment" error mean? How
do I track it down?
6.1: I had the definition char a[6] in one source file, and in
another I declared extern char *a. Why didn't it work?
A: The declaration extern char *a simply does not match the actual
definition. The type pointer-to-type-T is not the same as
array-
of-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: But I heard that char a[] was identical to char *a.
References: K&R2 Sec. 5.5 p. 104; CT&P Sec. 4.5 pp. 64-5.
p = a;
f(a)
char a[];
{ ... }
f(a)
char *a;
{ ... }
A: The type.
#include <stdlib.h>
int *dynarray;
dynarray = malloc(10 * sizeof(int));
#include <stdlib.h>
int (*array4)[NCOLUMNS] =
(int (*)[NCOLUMNS])malloc(nrows * sizeof
(*array4));
but the syntax starts getting horrific and at most one dimension
may be specified at run time.
int realarray[10];
int *array = &realarray[-1];
References: K&R2 Sec. 5.3 p. 100, Sec. 5.4 pp. 102-3, Sec. A7.7
pp. 205-6; ANSI Sec. 3.3.6; ISO Sec. 6.3.6; Rationale
Sec. 3.2.2.3.
A: The rule (see question 6.3) by which arrays decay into pointers
is not applied recursively. An array of arrays (i.e. a two-
dimensional 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.)
int array[NROWS][NCOLUMNS];
f(array);
f(int a[][NCOLUMNS])
{ ... }
or
References: K&R1 Sec. 5.10 p. 110; K&R2 Sec. 5.9 p. 113; H&S
Sec. 5.4.3 p. 126.
This function could be called with the array from question 6.18
as
int array[NROWS][NCOLUMNS];
int **array1; /* ragged */
int **array2; /* contiguous */
int *array3; /* "flattened" */
int (*array4)[NCOLUMNS];
The following two calls would probably work on most systems, but
involve questionable casts, and work only if the dynamic
ncolumns matches the static NCOLUMNS:
If you can understand why all of the above calls work and are
written as they are, and if you understand why the combinations
that are not listed would not work, then you have a *very* good
understanding of arrays and pointers in C.
6.21: Why doesn't sizeof properly report the size of an array when the
array is a parameter to a function?
char *answer;
printf("Type something:\n");
gets(answer);
printf("You typed \"%s\"\n", answer);
#include <stdio.h>
#include <string.h>
7.3: But the man page for strcat() says that it takes two char *'s as
arguments. How am I supposed to know to allocate things?
char *itoa(int n)
{
char retbuf[20]; /* WRONG */
sprintf(retbuf, "%d", n);
return retbuf; /* WRONG */
}
7.7: Why does some code carefully cast the values returned by malloc
to the pointer type being allocated?
References: ANSI Sec. 3.3.3.4; ISO Sec. 6.3.3.4; H&S Sec. 7.5.2
p. 195.
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.
7.16: I'm allocating a large array for some numeric work, using the
line
A: Notice that 300 x 300 is 90,000, which will not fit in a 16-bit
int, even before you multiply it by sizeof(double) (see question
1.1). 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 300 * (300 * 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?
7.20: You can't use dynamically-allocated memory after you free it,
can you?
7.25: I have a program which mallocs and later frees a lot of memory,
but memory usage (as reported by ps) doesn't seem to go back
down.
7.27: So can I query the malloc package to find out how big an
allocated block is?
A: Not portably.
References: ANSI Sec. 4.10.3.4; ISO Sec. 7.10.3.4; H&S Sec. 16.3
p. 388.
p = malloc(m * n);
memset(p, 0, m * n);
strcat(string, '!');
work?
strcat(string, "!");
char *string;
...
if(string == "value") {
/* string matches "value" */
...
}
if(strcmp(string, "value") == 0) {
/* string matches "value" */
...
}
char a[14];
a = "Hello, world!";
A: Strings are arrays, and you can't assign arrays directly. Use
strcpy() instead:
8.6: How can I get the numeric (character set) value corresponding to
a character, or vice versa?
References: ANSI Sec. 3.1.3.4; ISO Sec. 6.1.3.4; H&S Sec. 2.7.3
p. 29.
These don't buy anything (see question 9.2 below; see also
questions 5.12 and 10.2).
if((a == b) == TRUE)
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".
#define begin {
#define end }
References: H&S Sec. 3.3.2 p. 45; CT&P Sec. 6.3 pp. 82-3.
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?)
References: K&R2 Sec. 4.5 pp. 81-2; H&S Sec. 9.2.3 p. 267; CT&P
Sec. 4.6 pp. 66-7.
#ifndef HFILENAME_USED
#define HFILENAME_USED
...header file contents...
#endif
10.9: I'm getting strange syntax errors on the very first declaration
in a file, but it looks fine.
References: ANSI Sec. 3.8.1; ISO Sec. 6.8.1; H&S Sec. 7.11.1
p. 225.
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?
10.20: I have some old code that tries to construct identifiers with a
macro like
TRACE(count);
as
printf("TRACE: %d\count", count);
DEBUG("i = %d" _ i)
and
ISO Sales
Case Postale 56
CH-1211 Geneve 20
Switzerland
int func(x)
float x;
{ ...
References: K&R1 Sec. A7.1 p. 186; K&R2 Sec. A7.3.2 p. 202; ANSI
Sec. 3.3.2.2, Sec. 3.5.4.3; ISO Sec. 6.3.2.2, Sec. 6.5.4.3;
Rationale Sec. 3.3.2.2, Sec. 3.5.4.3; H&S Sec. 9.2 pp. 265-7,
Sec. 9.4 pp. 272-3.
struct x;
const int n = 5;
int a[n];
References: ANSI Sec. 3.4; ISO Sec. 6.4; H&S Secs. 7.11.2,7.11.3
pp. 226-7.
You must use explicit casts (e.g. (const char **) in this case)
when assigning (or passing) pointers which have qualifier
mismatches at other than the first level of indirection.
11.12: Can I declare main() as void, to shut off these annoying "main
returns no value" messages?
References: ANSI Sec. F.5.1; ISO Sec. G.5.1; H&S Sec. 20.1 pp.
416-7.
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.
11.15: The book I've been using, _C Programing for the Compleat Idiot_,
always uses void main().
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.
#define Str(x) #x
#define Xstr(x) Str(x)
#define OP plus
char *opname = Xstr(OP);
TRACE(i, %d);
were expanded as
11.19: I'm getting strange syntax errors inside lines I've #ifdeffed
out.
11.20: What are #pragmas and what are they good for?
References: ANSI Sec. 3.8.6; ISO Sec. 6.8.6; H&S Sec. 3.7 p. 61.
11.21: What does "#pragma once" mean? I found it in some header files.
Most of the time, you should let the compiler count the
initializers when initializing arrays (in the case of the
initializer "abc", of course, the computed size will be 4).
References: ANSI Sec. 3.5.7; ISO Sec. 6.5.7; H&S Sec. 4.6.4 p.
98.
References: ANSI Sec. 4.10.3; ISO Sec. 7.10.3; PCS Sec. 16.1 p.
386.
11.27: Why does the ANSI Standard not guarantee more than six case-
insensitive characters of external identifier significance?
Finally, are you sure you really need to convert lots of old
code to ANSI C? The old-style function syntax is still
acceptable (except for variadic functions; see section 15), and
a hasty conversion can easily introduce bugs. (See question
11.3.)
11.32: Why won't the Frobozz Magic C Compiler, which claims to be ANSI
compliant, accept this code? I know that the code is ANSI,
because gcc accepts it.
References: ANSI Sec. 1.6; ISO Sec. 3.10, Sec. 3.16, Sec. 3.17;
Rationale Sec. 1.6.
11.34: I'm appalled that the ANSI Standard leaves so many issues
undefined. Isn't a Standard's whole job to standardize these
things?
char c;
while((c = getchar()) != EOF) ...
References: K&R1 Sec. 1.5 p. 14; K&R2 Sec. 1.5.1 p. 16; ANSI
Sec. 3.1.2.5, Sec. 4.9.1, Sec. 4.9.7.5; ISO Sec. 6.1.2.5,
Sec. 7.9.1, Sec. 7.9.7.5; H&S Sec. 5.1.3 p. 116, Sec. 15.1,
Sec. 15.6; CT&P Sec. 5.1 p. 70; PCS Sec. 11 p. 157.
while(!feof(infp)) {
fgets(buf, MAXLINE, infp);
fputs(buf, outfp);
}
References: K&R2 Sec. 7.6 p. 164; ANSI Sec. 4.9.3, Sec. 4.9.7.1,
Sec. 4.9.10.2; ISO Sec. 7.9.3, Sec. 7.9.7.1, Sec. 7.9.10.2; H&S
Sec. 15.14 p. 382.
12.5: How can I read one character at a time, without waiting for the
RETURN key?
References: K&R1 Sec. 7.3 p. 147; K&R2 Sec. 7.2 p. 154; ANSI
Sec. 4.9.6.1; ISO Sec. 7.9.6.1.
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. (printf() does accept %Lf, for long double.) 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.
References: K&R1 Sec. 7.3; K&R2 Sec. 7.2; ANSI Sec. 4.9.6.1; ISO
Sec. 7.9.6.1; H&S Sec. 15.11.6; CT&P Sec. A.1.
12.11: How can I print numbers with commas separating the thousands?
What about currency formatted numbers?
References: ANSI Sec. 4.4; ISO Sec. 7.4; H&S Sec. 11.6 pp. 301-
4.
double d;
scanf("%f", &d);
work?
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.
References: K&R2 Sec. B1.3 pp. 245-6; ANSI Sec. 4.9.6.2; ISO
Sec. 7.9.6.2; H&S Sec. 15.8 pp. 357-64.
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()!
References: ANSI Sec. 4.9.6.2; ISO Sec. 7.9.6.2; H&S Sec. 15.8
pp. 357-64.
References: ANSI Sec. 4.9.6.2; ISO Sec. 7.9.6.2; H&S Sec. 15.8
pp. 357-64.
12.20: Why does everyone say not to use scanf()? What should I use
instead?
12.21: How can I tell how much destination buffer space I'll need for
an arbitrary sprintf call? How can I avoid overflowing the
destination buffer with sprintf()?
A: There are not (yet) any good answers to either of these
excellent questions, and this represents perhaps the biggest
deficiency in the traditional stdio library.
When the format string being used with sprintf() is known and
relatively simple, you can usually predict a buffer size in an
ad-hoc way. If the format consists of one or two %s's, you can
count the fixed characters in the format string yourself (or let
sizeof count them for you) and add in the result of calling
strlen() on the string(s) to be inserted. The number of
characters produced by %d is no more than
If there's any chance that the buffer might not be big enough,
you won't want to call sprintf() without some guarantee that the
buffer will not overflow and overwrite some other part of
memory. If the format string is known, you can limit %s
expansion by using %.Ns for some N, or %.*s (see also question
12.10). Several stdio's (including GNU and 4.4bsd) provide the
obvious snprintf() function, which can be used like this:
12.26: How can I flush pending input so that a user's typeahead isn't
read at the next prompt? Will fflush(stdin) work?
References: ANSI Sec. 4.9.5.2; ISO Sec. 7.9.5.2; H&S Sec. 15.2.
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, and that overwriting in text mode may
truncate the file at that point. See also question 19.14.
References: ANSI Sec. 4.9.5.4; ISO Sec. 7.9.5.4; H&S Sec. 15.2.
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?
References: ANSI Sec. 4.3.2; ISO Sec. 7.3.2; H&S Sec. 12.9 pp.
320-1; PCS p. 182.
References: ANSI Sec. 4.10.5.2; ISO Sec. 7.10.5.2; H&S Sec. 20.5
p. 419.
References: ANSI Sec. 4.10.5.2; ISO Sec. 7.10.5.2; H&S Sec. 20.5
p. 419.
References: Knuth Sec. 5.2.1 pp. 80-102, Sec. 5.2.4 pp. 159-168;
Sedgewick Sec. 8 pp. 98-100, Sec. 12 pp. 163-175.
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
try invoking it from within your program: see questions 19.27
and 19.30.
13.12: How can I get the current date or time of day in a C program?
#include <stdio.h>
#include <time.h>
main()
{
time_t now;
time(&now);
printf("It's %.24s.\n", ctime(&now));
return 0;
}
References: K&R2 Sec. B10 pp. 255-7; ANSI Sec. 4.12; ISO
Sec. 7.12; H&S Sec. 18.
13.14: How can I add N days to a date? How can I find the difference
between two dates?
rand() % N /* POOR */
(int)((double)rand() / ((double)RAND_MAX + 1) * N)
rand() / (RAND_MAX / N + 1)
13.17: Each time I run my program, I get the same sequence of numbers
back from rand().
#include <stdlib.h>
#include <math.h>
double gaussrand()
{
static double V1, V2, S;
static int phase = 0;
double X;
if(phase == 0) {
do {
double U1 = (double)rand() /
RAND_MAX;
double U2 = (double)rand() /
RAND_MAX;
V1 = 2 * U1 - 1;
V2 = 2 * U2 - 1;
S = V1 * V1 + V2 * V2;
} while(S >= 1 || S == 0);
phase = 1 - phase;
return X;
}
See the extended versions of this list (see question 20.40) for
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.
A: 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
line.) See also question 13.28.
13.28: What does it mean when the linker says that _end is undefined?
14.1: When I set a float variable to, say, 3.1, why is printf()
printing it as 3.0999999?
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.
These problems are no worse for C than they are for any other
computer language. Certain aspects of floating-point are
usually defined as "however the processor does them" (see also
question 11.34), otherwise a compiler for a machine without the
"right" model would have to do prohibitively expensive
emulations.
double a, b;
...
if(a == b) /* WRONG */
#include <math.h>
(int)(x + 0.5)
References: ANSI Sec. 4.5.5.1; ISO Sec. 7.5.5.1; H&S Sec. 17.6
p. 393.
14.9: How do I test for IEEE NaN and other special values?
14.13: I'm having trouble with a Turbo C program which crashes and says
something like "floating point formats not linked."
15.2: How can %f be used for both float and double arguments in
printf()? Aren't they different types?
References: ANSI Sec. 3.3.2.2; ISO Sec. 6.3.2.2; H&S Sec. 6.3.5
p. 177, Sec. 9.4 pp. 272-3.
printf("%d", n);
if(first == NULL)
return NULL;
len = strlen(first);
va_start(argp, first);
va_end(argp);
if(retbuf == NULL)
return NULL; /* error */
(void)strcpy(retbuf, first);
va_end(argp);
return retbuf;
}
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.)
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?
#include <stdio.h>
#include <stdarg.h>
References: H&S Sec. 11.4 pp. 296-9; CT&P Sec. A.2 pp. 134-139;
PCS Sec. 11 pp. 184-5, Sec. 13 p. 250.
15.8: How can I discover how many arguments a function was actually
called with?
int f(...)
{
}
va_arg(argp, float)
working?
15.13: How can I call a function with an argument list built up at run
time?
16.2a: I'm getting baffling syntax errors which make no sense at all,
and it seems like large chunks of my program aren't being
compiled.
16.2b: Why isn't my procedure call working? The compiler seems to skip
right over it.
myprocedure;
myprocedure();
16.3: This program crashes before it even runs! (When single-stepping
with a debugger, it dies before the first statement in main().)
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:
crash?
References: ANSI Sec. 3.1.4; ISO Sec. 6.1.4; H&S Sec. 2.7.4 pp.
31-2.
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.
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.
17.3: Here's a neat trick for checking whether two strings are equal:
if(!strcmp(s1, s2))
if(x = 0)
if(0 = x)
17.5: I came across some code that puts a (void) cast before each call
to printf(). Why?
A: printf() does return a value, though few programs bother to
check the return values from each call. Since some compilers
(and lint) will warn about discarded return values, an explicit
cast to (void) is a way of saying "Yes, I've decided to ignore
the return value from this call, but please continue to warn me
about other (perhaps inadvertently) ignored return values."
It's also common to use void casts on calls to strcpy() and
strcat(), since the return value is never surprising.
17.9: Where can I get the "Indian Hill Style Guide" and other coding
standards?
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
17.10: Some people say that goto's are evil and that I should never use
them. Isn't that a bit extreme?
http://www.qucis.queensu.ca/Software-
Engineering/Cmetrics.html ;
there is also a package sold
by McCabe and Associates
a "selective" C
preprocessor see question 10.18
18.4: I just typed in this program, and it's acting strangely. Can
you see anything wrong with it?
A: See if you can run lint first (perhaps with the -a, -c, -h, -p
or other options). Many C compilers are really only half-
compilers, electing not to diagnose numerous source code
difficulties which would not actively preclude code generation.
18.5: How can I shut off the "warning: possible pointer alignment
problem" message which lint gives me for each call to malloc()?
Gimpel Software
3207 Hogarth Lane
Collegeville, PA 19426 USA
(+1) 610 584 4261
gimpel@netaxs.com
A: No. First of all, prototypes work only if they are present and
correct; an inadvertently incorrect prototype is worse than
useless. Secondly, lint checks consistency across multiple
source files, and checks data declarations as well as functions.
Finally, an independent program like lint will probably always
be more scrupulous at enforcing compatible, portable coding
practices than will any particular, implementation-specific,
feature- and extension-laden compiler.
On some Unix machines you can try typing learn c at the shell
prompt.
Finally, the author of this FAQ list teaches a C class and has
begun putting its notes on the web; they are at
http://www.eskimo.com/~scs/cclass/cclass.html .
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. Several sets of annotations and
errata are available on the net, see e.g.
http://www.csd.uwo.ca/~jamie/.Refs/.Footnotes/C-annotes.html,
http://www.eskimo.com/~scs/cclass/cclass.html, and
http://www.lysator.liu.se/c/c-errata.html#main .
Though not suitable for learning C from scratch, this FAQ list
has been published in book form; see the Bibliography.
References: K&R1 Sec. A18 pp. 214-219; K&R2 Sec. A13 pp. 234-
239; ANSI Sec. A.2; ISO Sec. B.2; H&S pp. 423-435 Appendix B.
18.16: Where and how can I get copies of all these freely distributable
programs?
Those are some of the easy parts of the question to answer. The
hard part is in the details -- this article cannot begin to
track or list all of the available archive sites or all of the
various ways of accessing them. If you have access to the net
at all, you probably have access to more up-to-date information
about active sites and useful access methods than this FAQ list
does.
19.1: How can I read a single character from the keyboard without
waiting for the RETURN key? How can I stop characters from
being echoed on the screen as they're typed?
References: PCS Sec. 10 pp. 128-9, Sec. 10.1 pp. 130-1; POSIX
Sec. 7.
19.2: How can I find out if there are characters available for reading
(and if so, how many)? Alternatively, how can I do a read that
will not block if there are no characters available?
References: PCS Sec. 5.1.4 pp. 54-60, Sec. 5.1.5 pp. 60-62.
19.5: How do I read the arrow keys? What about function keys?
fprintf(ofd, "\033[J");
A: Once upon a time, Unix had a fairly nice little set of device-
independent plot routines described in plot(3) and plot(5), but
they've largely fallen into disuse.
19.11: How can I check whether a file exists? I want to warn the user
if a requested input file is missing.
19.12: How can I find out the size of a file, prior to reading it in?
Under Unix, the stat() call will give you an exact answer.
Several other systems supply a Unix-like stat() which will give
an approximate answer. You can fseek() to the end and then use
ftell(), or maybe try fstat(), but these tend to have problems:
fstat() is not portable, and generally tells you the same thing
stat() tells you; ftell() is not guaranteed to return a byte
count except for binary files. Some systems provide routines
called filesize() or filelength(), but these are not portable,
either.
Are you sure you have to determine the file's size in advance?
Since the most accurate way of determining the size of a file as
a C program will see it is to open the file and read it, perhaps
you can rearrange the code to learn the size as it reads.
19.12a: How can I find the modification date and time of a file?
19.14: How can I insert or delete a line (or record) in the middle of a
file?
19.15: How can I recover the file name given an open stream or file
descriptor?
A: This problem is, in general, insoluble. Under Unix, for
instance, a scan of the entire disk (perhaps involving special
permissions) would theoretically be required, and would fail if
the descriptor were connected to a pipe or referred to a deleted
file (and could give a misleading answer for a file with
multiple links). It is best to remember the names of files
yourself when you open them (perhaps with a wrapper function
around fopen()).
19.17: Why can't I open a file by its explicit path? The call
fopen("c:\newdir\file.dat", "r")
is failing.
fopen("c:\\newdir\\file.dat", "r");
fopen("c:/newdir/file.dat", "r");
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.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!
References: K&R1 Sec. A14.4 p. 210; K&R2 Sec. A6.6 p. 199; ANSI
Sec. 3.3.4; ISO Sec. 6.3.4; Rationale Sec. 3.3.4; H&S Sec. 6.2.7
pp. 171-2.
19.30: How can I invoke another program or command and trap its output?
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: K&R1 Sec. 5.11 p. 111; K&R2 Sec. 5.10 p. 115; ANSI
Sec. 2.1.2.2.1; ISO Sec. 5.1.2.2.1; H&S Sec. 20.1 p. 416.
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.)
19.36: How can I read in an object file and jump to routines in it?
long int i;
for(i = 0; i < 1000000; i++)
;
References: H&S Sec. 18.1 pp. 398-9; PCS Sec. 12 pp. 197-8,215-
6; POSIX Sec. 4.5.2.
#include <signal.h>
signal(SIGINT, SIG_IGN);
The test and extra call ensure that a keyboard interrupt typed
in the foreground won't inadvertently interrupt a program
running in the background (and it doesn't hurt to code calls to
signal() this way on any system).
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?
References: K&R1 Sec. 5.11 pp. 110-114; K&R2 Sec. 5.10 pp. 114-
118; ANSI Sec. 2.1.2.2.1; ISO Sec. 5.1.2.2.1; H&S Sec. 20.1 p.
416; PCS Sec. 5.6 pp. 81-2, Sec. 11 p. 159, pp. 339-40 Appendix
F; Schumacher, ed., _Software Solutions in C_ Sec. 4 pp. 75-85.
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?
Then, search the table for the name, and call via the associated
function pointer. See also questions 2.15 and 19.36.
int x = 1;
if(*(char *)&x == 1)
printf("little-endian\n");
else printf("big-endian\n");
A: 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.
For more information about "binary" I/O, see question 2.11. See
also questions 8.6 and 13.1.
20.12: What is the most efficient way to count the number of bits which
are set in a value?
A: Many "bit-fiddling" problems like this one can be sped up and
streamlined using lookup tables (but see question 20.13 below).
20.14: Are pointers really faster than arrays? How much do function
calls slow things down? Is ++i faster than i = i + 1?
References: K&R1 Sec. 3.4 p. 55; K&R2 Sec. 3.4 p. 58; ANSI
Sec. 3.6.4.2; ISO Sec. 6.6.4.2; H&S Sec. 8.7 p. 248.
References: K&R1 Sec. 3.4 p. 55; K&R2 Sec. 3.4 p. 58; ANSI
Sec. 3.6.4.2; ISO Sec. 6.6.4.2; Rationale Sec. 3.6.4.2; H&S
Sec. 8.7 p. 248.
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.
References: K&R1 Sec. A18.3 p. 218; ANSI Sec. 3.3.3, Sec. 3.6.6;
ISO Sec. 6.3.3, Sec. 6.6.6; H&S Sec. 8.9 p. 254.
References: K&R1 Sec. A2.1 p. 179; K&R2 Sec. A2.2 p. 192; ANSI
Sec. 3.1.9 (esp. footnote 26), Appendix E; ISO Sec. 6.1.9, Annex
F; Rationale Sec. 3.1.9; H&S Sec. 2.2 pp. 18-9; PCS Sec. 10 p.
130.
20.25: How can I call FORTRAN (C++, BASIC, Pascal, Ada, LISP) functions
from C? (And vice versa?)
A: 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; the two also define the meaning
of some common constructs differently. 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. See also questions 8.9 and 20.20.
References: K&R2 Sec. 6.6; Knuth Sec. 6.4 pp. 506-549 Volume 3;
Sedgewick Sec. 16 pp. 231-244.
20.31: How can I find the day of the week given the date?
dayofweek(y, m, d) /* 0 = Sunday */
int y, m, d; /* 1 <= m <= 12, y > 1752 or so
*/
{
static int t[] = {0, 3, 2, 5, 0, 3, 5, 1, 4, 6,
2, 4};
y -= m < 3;
return (y + y/4 - y/100 + y/400 + t[m-1] + d) %
7;
}
A: Yes and no, respectively. The full expression for the present
Gregorian calendar is
20.34: Here's a good puzzle: how do you write a program which produces
its own source code as its output?
{apple,pyramid,sun,uunet}!hoptoad!judges or
judges@toad.com
20.40: Where can I get extra copies of this list? What about back
issues?
Bibliography
G.E.P. Box and Mervin E. Muller, "A Note on the Generation of Random
Normal Deviates," _Annals of Mathematical Statistics_, Vol. 29 #2, June,
1958, pp. 610-611.
P.J. Plauger, _The Standard C Library_, Prentice Hall, 1992, ISBN 0-13-
131509-9.
Acknowledgements
Steve Summit
scs@eskimo.com