Adsnese

Ad

Monday, December 24, 2007

C Interview Questions And Answers- 26

8.1 Why doesn't

strcat(string, '!');

work?

8.2 I'm checking a string to see if it matches a particular value. Why isn't this code working?

char *string;
...
if(string == "value") {
/* string matches "value" */
...
}

8.3 If I can say

char a[] = "Hello, world!";

why can't I say

char a[14];
a = "Hello, world!";

8.4 I can't get strcat to work. I tried

char *s1 = "Hello, ";
char *s2 = "world!";
char *s3 = strcat(s1, s2);

but I got strange results.

8.5 What is the difference between these initializations?

char a[] = "string literal";
char *p = "string literal";

My program crashes if I try to assign a new value to p[i].

8.6 How can I get the numeric value (i.e. ASCII or other character set code) corresponding to a character, or vice versa?

8.7 Does C have anything like the ``substr'' (extract substring) routine present in other languages?

8.8 I'm reading strings typed by the user into an array, and then printing them out later. When the user types a sequence like \n, why isn't it being handled properly?

8.9 I think something's wrong with my compiler: I just noticed that sizeof('a') is 2, not 1 (i.e. not sizeof(char)).

8.10 I'm starting to think about multinational character sets, and I'm worried about the implications of making sizeof(char) be 2 so that 16-bit character sets can be represented.

C Interview Questions And Answers- 25

7.1 Why doesn't this fragment work?

char *answer;
printf("Type something:\n");
gets(answer);
printf("You typed \"%s\"\n", answer);

7.2 I can't get strcat to work. I tried

char *s1 = "Hello, ";
char *s2 = "world!";
char *s3 = strcat(s1, s2);

but I got strange results.

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?

7.3b I just tried the code

char *p;
strcpy(p, "abc");

and it worked. How? Why didn't it crash?

7.3c How much memory does a pointer variable allocate?

7.4 I'm reading lines from a file into an array, with this code:

char linebuf[80];
char *lines[100];
int i;

for(i = 0; i <>
char *p = fgets(linebuf, 80, fp);
if(p == NULL) break;
lines[i] = p;
}

Why do all the lines end up containing copies of the last line?

7.5a I have a function that is supposed to return a string, but when it returns to its caller, the returned string is garbage.

7.5b So what's the right way to return a string or other aggregate?

7.6 Why am I getting ``warning: assignment of pointer from integer lacks a cast'' for calls to malloc?

7.7 Why does some code carefully cast the values returned by malloc to the pointer type being allocated?

7.7b What's wrong with casting malloc's return value?

7.7c In a call to malloc, what does an error like ``Cannot convert `void *' to `int *''' mean?

7.8 I see code like

char *p = malloc(strlen(s) + 1);
strcpy(p, s);

Shouldn't that be malloc((strlen(s) + 1) * sizeof(char))?

7.9 I wrote a little wrapper around malloc, but it doesn't work:

#include
#include

mymalloc(void *retp, size_t size)
{
retp = malloc(size);
if(retp == NULL) {
fprintf(stderr, "out of memory\n");
exit(EXIT_FAILURE);
}
}

7.10 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);

7.10a What's wrong with this initialization?

char *p = malloc(10);

My compiler is complaining about an ``invalid initializer'', or something.

7.10b How can I shut off the ``warning: possible pointer alignment problem'' message which lint gives me for each call to malloc?

7.11 How can I dynamically allocate arrays?

7.12 How can I find out how much memory is available?

7.13 What should malloc(0) do? Return a null pointer or a pointer to 0 bytes?

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?

7.15 malloc is returning crazy pointer values, but I did read question 7.6 and I have included the line

extern void *malloc();

before I call it.

7.16 I'm allocating a large array for some numeric work, using the line

double *array = malloc(300 * 300 * 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.

7.17 I've got 8 meg of memory in my PC. Why can I only seem to malloc 640K or so?

7.18 My application depends heavily on dynamic allocation of nodes for data structures, and malloc/free overhead is becoming a bottleneck. What can I do?

7.19 My program is crashing, apparently somewhere down inside malloc, but I can't see anything wrong with it. Is there a bug in malloc?

7.19b

I'm dynamically allocating an array, like this:

int *iarray = (int *)malloc(nints);

malloc isn't returning NULL, but the code isn't working.

7.20 You can't use dynamically-allocated memory after you free it, can you?

7.21 Why isn't a pointer null after calling free?
How unsafe is it to use (assign, compare) a pointer value after it's been freed?

7.22 When I call malloc to allocate memory for a pointer which is local to a function, do I have to explicitly free it?

7.23 I'm allocating structures which contain pointers to other dynamically-allocated objects. When I free a structure, do I also have to free each subsidiary pointer?

7.24 Must I free allocated memory before the program exits?

7.25 I have a program which mallocs and later frees a lot of memory, but I can see from the operating system that memory usage doesn't actually go back down.

7.26 How does free know how many bytes to free?

7.27 So can I query the malloc package to find out how big an allocated block is?

7.28 Why doesn't sizeof tell me the size of the block of memory pointed to by a pointer?

7.29 Having dynamically allocated an array (as in question 6.14), can I change its size?

7.30 Is it legal to pass a null pointer as the first argument to realloc? Why would you want to?

7.31 What's the difference between calloc and malloc? Which should I use? Is it safe to take advantage of calloc's zero-filling? Does free work on memory allocated with calloc, or do you need a cfree?

7.32 What is alloca and why is its use discouraged?

C Interview Questions And Answers- 24

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?

6.2 But I heard that char a[] was identical to char *a.

6.3 So what is meant by the ``equivalence of pointers and arrays'' in C?

6.4 If they're so different, then why are array and pointer declarations interchangeable as function formal parameters?

6.4b So arrays are passed by reference, even though the rest of C uses pass by value?

6.5 Why can't I do something like this?

extern char *getpass();
char str[10];
str = getpass("Enter password: ");

6.6 If you can't assign to arrays, then how can

int f(char str[])
{
if(str[0] == '\0')
str = "none";
...
}

work?

6.6b And what about this? Isn't this an array assignment?

char a[] = "Hello, world!\n";

6.7 How can an array be an lvalue, if you can't assign to it?

6.8 Practically speaking, what is the difference between arrays and pointers?

6.9 Someone explained to me that arrays were really just constant pointers.

6.10 I'm still mystified. Is a pointer a kind of array, or is an array a kind of pointer?

6.11 I came across some ``joke'' code containing the ``expression'' 5["abcdef"] . How can this be legal C?

6.12 Since array references decay into pointers, if arr is an array, what's the difference between arr and &arr?

6.13 How do I declare a pointer to an array?

6.14 How can I set an array's size at run time?
How can I avoid fixed-sized arrays?

6.15 How can I declare local arrays of a size matching a passed-in array?

6.16 How can I dynamically allocate a multidimensional array?

6.17 Here's a neat trick: if I write

int realarray[10];
int *array = &realarray[-1];

I can treat array as if it were a 1-based array.

6.18 My compiler complained when I passed a two-dimensional array to a function expecting a pointer to a pointer.

6.19 How do I write functions which accept two-dimensional arrays when the width is not known at compile time?

6.20 How can I use statically- and dynamically-allocated multidimensional arrays interchangeably when passing them to functions?

6.21 Why doesn't sizeof properly report the size of an array when the array is a parameter to a function? I have a test routine

f(char a[10])
{
int i = sizeof(a);
printf("%d\n", i);
}

and it prints 4, not 10.

6.22 How can code in a file where an array is declared as extern (i.e. it is defined, and its size determined, in some other file) determine the size of the array? sizeof doesn't seem to work.

6.23 I want to know how many elements are in an array, but sizeof yields the size in bytes.

6.24 Is there a way to have an array of bits?

C Interview Questions And Answers- 23

5.1 What is this infamous null pointer, anyway?

5.2 How do I get a null pointer in my programs?

5.3 Is the abbreviated pointer comparison ``if(p)'' to test for non-null pointers valid? What if the internal representation for null pointers is nonzero?

5.4 What is NULL and how is it defined?

5.5 How should NULL be defined on a machine which uses a nonzero bit pattern as the internal representation of a null pointer?

5.6 If NULL were defined as follows:

#define NULL ((char *)0)

wouldn't that make function calls which pass an uncast NULL work?

5.7 My vendor provides header files that #define NULL as 0L. Why?

5.8 Is NULL valid for pointers to functions?

5.9 If NULL and 0 are equivalent as null pointer constants, which should I use?

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?

5.11 I once used a compiler that wouldn't work unless NULL was used.

5.12 I use the preprocessor macro

#define Nullptr(type) (type *)0

to help me build null pointers of the correct type.

5.13 This is strange. NULL is guaranteed to be 0, but the null pointer is not?

5.14 Why is there so much confusion surrounding null pointers? Why do these questions come up so often?

5.15 I'm confused. I just can't understand all this null pointer stuff.

5.16 Given all the confusion surrounding null pointers, wouldn't it be easier simply to require them to be represented internally by zeroes?

5.17 Seriously, have any actual machines really used nonzero null pointers, or different representations for pointers to different types?

5.18 Is a run-time integral value of 0, cast to a pointer, guaranteed to be a null pointer?

5.19 How can I access an interrupt vector located at the machine's location 0? If I set a pointer to 0, the compiler might translate it to some nonzero internal null pointer value.

5.20 What does a run-time ``null pointer assignment'' error mean? How can I track it down?

C Interview Questions And Answers- 22

4.1 What are pointers really good for, anyway?

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);

4.3 Does *p++ increment p, or what it points to?

4.4 I'm trying to use pointers to manipulate an array of ints. What's wrong with this code?

int array[5], i, *ip;
for(i = 0; i <>
ip = array;
printf("%d\n", *(ip + 3 * sizeof(int)));

I expected the last line to print 3, but it printed garbage.

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?

4.6 Why can't I perform arithmetic on a void * pointer?

4.7 I've got some code that's trying to unpack external structures, but it's crashing with a message about an ``unaligned access.'' What does this mean?

4.8 I have a function which accepts, and is supposed to initialize, a pointer:

void f(int *ip)
{
static int dummy = 5;
ip = &dummy;
}

But when I call it like this:

int *ip;
f(ip);

the pointer in the caller remains unchanged.

4.9 Suppose I want to write a function that takes a generic pointer as an argument and I want to simulate passing it by reference. Can I give the formal parameter type void **, and do something like this?

void f(void **);
double *dp;
f((void **)&dp);

4.10 I have a function

extern int f(int *);

which accepts a pointer to an int. How can I pass a constant by reference? A call like

f(&5);

doesn't seem to work.

4.11 Does C even have ``pass by reference''?

4.12 I've seen different syntax used for calling functions via pointers. What's the story?

4.13 What's the total generic pointer type? My compiler complained when I tried to stuff function pointers into a void *.

4.14 How are integers converted to and from pointers? Can I temporarily stuff an integer into a pointer, or vice versa?

4.15 How do I convert an int to a char *? I tried a cast, but it's not working.

4.16 What's wrong with this declaration?

char* p1, p2;

I get errors when I try to use p2.

4.17 What are ``near'' and ``far'' pointers?

C Interview Questions And Answers- 22

3.1 Why doesn't this code:

a[i] = i++;

work?

3.2 Under my compiler, the code

int i = 7;
printf("%d\n", i++ * i++);

prints 49. Regardless of the order of evaluation, shouldn't it print 56?

3.3 I've experimented with the code

int i = 3;
i = i++;

on several compilers. Some gave i the value 3, and some gave 4. Which compiler is correct?

3.3b Here's a slick expression:

a ^= b ^= a ^= b

It swaps a and b without using a temporary.

3.4 Can I use explicit parentheses to force the order of evaluation I want, and control these side effects? Even if I don't, doesn't precedence dictate it?

3.5 But what about the && and || operators?
I see code like ``while((c = getchar()) != EOF && c != '\n')'' ...

3.6 Is it safe to assume that the right-hand side of the && and || operators won't be evaluated if the left-hand side determines the outcome?

3.7 Why did

printf("%d %d", f1(), f2());

call f2 first? I thought the comma operator guaranteed left-to-right evaluation.

3.8 How can I understand complex expressions like the ones in this section, and avoid writing undefined ones? What's a ``sequence point''?

3.9 So if I write

a[i] = i++;

and I don't care which cell of a[] gets written to, the code is fine, and i gets incremented by one, right?

3.10a People keep saying that the behavior of i = i++ is undefined, but I just tried it on an ANSI-conforming compiler, and got the results I expected.

3.10b People told me that if I evaluated an undefined expression, or accessed an uninitialized variable, I'd get a random, garbage value. But I tried it, and got zero. What's up with that?

3.11 How can I avoid these undefined evaluation order difficulties if I don't feel like learning the complicated rules?

3.12a What's the difference between ++i and i++?

3.12b If I'm not using the value of the expression, should I use ++i or i++ to increment a variable?

3.13 I need to check whether one number lies between two others. Why doesn't

if(a < a =" 1000," b =" 1000;" c =" a" degc =" 5" b =" c">' change in ANSI C'' mean?

3.19 What's the difference between the ``unsigned preserving'' and ``value preserving'' rules?


C Interview Questions And Answers- 22

2.1 What's the difference between these two declarations?

struct x1 { ... };
typedef struct { ... } x2;

2.2 Why doesn't

struct x { ... };
x thestruct;

work?

2.3 Can a structure contain a pointer to itself?

2.4 How can I implement opaque (abstract) data types in C?

2.4b Is there a good way of simulating OOP-style inheritance, or other OOP features, in C?

2.5 Why does the declaration

extern int f(struct x *p);

give me an obscure warning message about ``struct x declared inside parameter list''?

2.6 I came across some code that declared a structure like this:

struct name {
int namelen;
char namestr[1];
};

and then did some tricky allocation to make the namestr array act like it had several elements, with the number recorded by namelen. How does this work? Is it legal or portable?

2.7 I heard that structures could be assigned to variables and passed to and from functions, but K&R1 says not.

2.8 Is there a way to compare structures automatically?

2.9 How are structure passing and returning implemented?

2.10 How can I pass constant values to functions which accept structure arguments? How can I create nameless, immediate, constant structure values?

2.11 How can I read/write structures from/to data files?

2.12 Why is my compiler leaving holes in structures, wasting space and preventing ``binary'' I/O to external data files? Can I turn this off, or otherwise control the alignment of structure fields?

2.13 Why does sizeof report a larger size than I expect for a structure type, as if there were padding at the end?

2.14 How can I determine the byte offset of a field within a structure?

2.15 How can I access structure fields by name at run time?

2.16 Does C have an equivalent to Pascal's with statement?

2.17 If an array name acts like a pointer to the base of an array, why isn't the same thing true of a structure?

2.18 This program works correctly, but it dumps core after it finishes. Why?

struct list {
char *item;
struct list *next;
}

/* Here is the main program. */

main(argc, argv)
{ ... }

2.19 What's the difference between a structure and a union, anyway?

2.20 Can I initialize unions?

2.21 Is there an automatic way to keep track of which field of a union is in use?

2.22 What's the difference between an enumeration and a set of preprocessor #defines?

2.23 Are enumerations really portable?
Aren't they Pascalish?

2.24 Is there an easy way to print enumeration values symbolically?

2.25 I came across some structure declarations with colons and numbers next to certain fields, like this:

struct record {
char *name;
int refcount : 4;
unsigned dirty : 1;
};

What gives?

2.26 Why do people use explicit masks and bit-twiddling code so much, instead of declaring bit-fields?

C Interview Questions And Answers- 22

1.1 How should I decide which integer type to use?

1.2 Why aren't the sizes of the standard types precisely defined?

1.3 Since C doesn't define sizes exactly, I've been using typedefs like int16 and int32. I can then define these typedefs to be int, short, long, etc. depending on what machine I'm using. That should solve everything, right?

1.4 What should the 64-bit type be on a machine that can support it?

1.5 What's wrong with this declaration?

char* p1, p2;

I get errors when I try to use p2.

1.6 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);

1.7 What's the best way to declare and define global variables and functions?

1.8 How can I implement opaque (abstract) data types in C?

1.9 How can I make a sort of ``semi-global'' variable, that is, one that's private to a few functions spread across a few source files?

1.10 Do all declarations for the same static function or variable have to include the storage class static?

1.11 What does extern mean in a function declaration?

1.12 What's the auto keyword good for?

1.13 What's the difference between using a typedef or a #define for a user-defined type?

1.14 I can't seem to define a linked list successfully. I tried

typedef struct {
char *item;
NODEPTR next;
} *NODEPTR;

but the compiler gave me error messages. Can't a structure in C contain a pointer to itself?

1.15 How can I define a pair of mutually referential structures? I tried

typedef struct {
int afield;
BPTR bpointer;
} *APTR;

typedef struct {
int bfield;
APTR apointer;
} *BPTR;

but the compiler doesn't know about BPTR when it is used in the first structure declaration.

1.16 What's the difference between these two declarations?

struct x1 { ... };
typedef struct { ... } x2;

1.17 What does

typedef int (*funcptr)();

mean?

1.18 I've got the declarations

typedef char *charp;
const charp p;

Why is p turning out const, instead of the characters pointed to?

1.19 I don't understand why I can't use const values in initializers and array dimensions, as in

const int n = 5;
int a[n];

1.20 What's the difference between const char *p, char const *p, and char * const p?

1.20b

What does it mean for a function parameter to be const? What do the two const's in

int f(const * const p)

mean?

1.21 How do I construct declarations of complicated types such as ``array of N pointers to functions returning pointers to functions returning pointers to char'', or figure out what similarly complicated declarations mean?

1.22 How can I declare a function that can return a pointer to a function of the same type? I'm building a state machine with one function for each state, each of which returns a pointer to the function for the next state. But I can't find a way to declare the functions--I seem to need a function returning a pointer to a function returning a pointer to a function returning a pointer to a function..., ad infinitum.

1.23 Can I declare a local array (or parameter array) of a size matching a passed-in array, or set by another parameter?

1.24 I have an extern array which is defined in one file, and used in another:

file1.c: file2.c:

int array[] = {1, 2, 3}; extern int array[];

Why doesn't sizeof work on array in file2.c?

1.25 My compiler is complaining about an invalid redeclaration of a function, but I only define it once and call it once.

1.25b What's the right declaration for main?
Is void main() correct?

1.26 My compiler is complaining about mismatched function prototypes which look fine to me.

1.27 I'm getting strange syntax errors on the very first declaration in a file, but it looks fine.

1.28 My compiler isn't letting me declare a big array like

double array[256][256];

1.29 How can I determine which identifiers are safe for me to use and which are reserved?

1.30 What am I allowed to assume about the initial values of variables and arrays which are not explicitly initialized?
If global variables start out as ``zero'', is that good enough for null pointers and floating-point zeroes?

1.31 This code, straight out of a book, isn't compiling:

int f()
{
char a[] = "Hello, world!";
}

1.31b What's wrong with this initialization?

char *p = malloc(10);

My compiler is complaining about an ``invalid initializer'', or something.

1.32 What is the difference between these initializations?

char a[] = "string literal";
char *p = "string literal";

My program crashes if I try to assign a new value to p[i].

1.33 Is char a[3] = "abc"; legal?

1.34 I finally figured out the syntax for declaring pointers to functions, but now how do I initialize one?

1.35 Can I initialize unions?

C Interview Questions And Answers- 21

11.5: Why does the declaration
extern int f(struct x *p);
give me an obscure warning message about "struct x introduced in
prototype scope"?
---
give me an obscure warning message about "struct x declared
inside parameter list"?
==========
A: "const char *p" (which can also be written "char const *p")
declares a pointer to a constant character (you can't change
the character); "char * const p" declares a constant pointer
---
any pointed-to characters); "char * const p" declares a constant
pointer to a (variable) character (i.e. you can't change the
pointer).
==========
A: The problem is older linkers which are under the control of
---
A: The problem is linkers which are under control of
neither the ANSI/ISO Standard nor the C compiler developers
on the systems which have them.
==========
If you're interested in writing portable code, you can ignore
the distinctions, as you'll want to avoid code that depends
---
the distinctions, as you'll usually want to avoid code that
depends on any of the three behaviors.
==========
A: The functions in locale.h begin to provide some support for
these operations, but there is no standard routine for doing
---
these operations, but there is no standard function for doing
either task.
==========
If you're worried about using floating point, you could use
---
If you'd rather not use floating point, another method is
rand() / (RAND_MAX / N + 1)
==========
A: In general, a header file contains only declarations.
---
A: In general, a header file contains only external declarations.
==========
how carefully your compiler's binary/decimal conversion routines
(such as those used by printf) have been written, you may see
discrepancies when numbers (especially low-precision floats) not
exactly representable in base 2 are assigned or read in and then
---
discrepancies when numbers not exactly representable in base 2
are assigned or read in and then printed (i.e. converted from
base 10 to base 2 and back again).
==========
Another possibility is to to format the value in question using
---
Another possibility is to format the value in question using
sprintf(): on many systems it generates strings like "NaN"
==========
A: Some compilers for small machines, including Borland's
---
A: Some compilers for small machines, including Turbo C
Ritchie's original PDP-11 compiler), leave out certain floating
==========
char *vstrcat(char *first, ...)
---
char *vstrcat(const char *first, ...)
==========
void error(char *fmt, ...)
---
void error(const char *fmt, ...)
==========
examples in questions 5.2 and 15.4). Finally, if their types
---
examples in questions 5.2 and 15.4). Finally, if the types
are predictable, you can pass an explicit count of the number of
==========
local arrays. Many systems have fixed-size stacks, and
---
local arrays. Many systems have fixed-size stacks, and even
those which perform dynamic stack allocation automatically
(e.g. Unix) can be confused when the stack tries to grow by a
huge chunk all at once.
==========
16.8: What do "Segmentation violation" and "Bus error" mean?
---
16.8: What do "Segmentation violation", "Bus error", and "General
protection fault" mean?
==========
Finally, the author of this FAQ list teaches a C class
and has placed its notes on the web; they are at
---
Finally, the author of this FAQ list once taught a couple of
C classes and has placed their notes on the web; they are at
==========
18.10: What's a good book for learning C?
---
18.10: What's a good book for learning C? What about advanced books
and references?
==========
The GNU libplot package maintains the same spirit and supports
many modern plot devices;
see http://www.gnu.org/software/plotutils/plotutils.html .
---
The GNU libplot library, written by Robert Maier, maintains
the same spirit and supports many modern plot devices; see
http://www.gnu.org/software/plotutils/plotutils.html .
==========
A: If the "size of a file" is the number of characters you'll be
able to read from it in C, it is difficult or impossible to
---
able to read from it in C, it can be difficult or impossible to
determine this number exactly.
==========
readdir() only returns file names; if you need more
---
readdir() returns just the file names; if you need more
information about the file, try calling stat().
==========
(Also, remember to call pclose().)
---
(Also, remember to call pclose() when you're done.)
==========
busy-wait, but this is only an option on a single-user, single-
tasking machine as it is terribly antisocial to any other
---
tasking machine, as it is terribly antisocial to any other
processes. Under a multitasking operating system, be sure to
==========
It is possible, and desirable, for *most* of a program to be
ANSI-compatible, deferring the system-dependent functionality to
a few routines in a few files which are rewritten for each
system ported to.
---
a few routines in a few files which are either heavily #ifdeffed
or rewritten entirely for each system ported to.
==========
or have the function return a structure containing the
desired values, or (in a pinch) consider global variables.
---
desired values, or (in a pinch) you could theoretically use
global variables.
==========
is not only clearer to the human reader, it is more likely to be
recognized by the compiler and turned into the most-efficient
code (e.g. using a swap instruction, if available).
---
code (e.g. perhaps even using an EXCH instruction).
==========
More information may be found in FORT.gz by Glenn Geers, available
via anonymous ftp from suphys.physics.su.oz.au in the src
directory.

cfortran.h, a C header file, simplifies C/FORTRAN interfacing on
many popular machines. It is available via anonymous ftp from
zebra.desy.de or at http://www-zeus.desy.de/~burow .
---
For FORTRAN, more information may be found in FORT.gz by Glenn
Geers, available via anonymous ftp from suphys.physics.su.oz.au
in the src directory. Burkhard Burow's header file cfortran.h
simplifies C/FORTRAN interfacing on many popular machines.
It is available via anonymous ftp from zebra.desy.de or at
http://www-zeus.desy.de/~burow .
==========
This FAQ list's maintainer also has available a list of a few
other commercial translation products, and some for more obscure
languages.
---
other translators.
==========
A: The contest is in a state of flux; see
---
A: The contest schedule varies over time; see
====================


Finally, here are a few questions which don't really need to be in
the posted-to-Usenet list every month. (As mentioned, though, they'll
live on in the web-based version.)

==========

1.22: How can I declare a function that can return a pointer to a
function of the same type? I'm building a state machine with
one function for each state, each of which returns a pointer to
the function for the next state. But I can't find a way to
declare the functions.

A: You can't quite do it directly. Either have the function return
a generic function pointer, with some judicious casts to adjust
the types as the pointers are passed around; or have it return a
structure containing only a pointer to a function returning that
structure.

==========

2.7: I heard that structures could be assigned to variables and
passed to and from functions, but K&R1 says not.

A: What K&R1 said (though this was quite some time ago by now) was
that the restrictions on structure operations would be lifted
in a forthcoming version of the compiler, and in fact structure
assignment and passing were fully functional in Ritchie's
compiler even as K&R1 was being published. A few ancient C
compilers may have lacked these operations, but all modern
compilers support them, and they are part of the ANSI C
standard, so there should be no reluctance to use them.

(Note that when a structure is assigned, passed, or returned,
the copying is done monolithically; the data pointed to by any
pointer fields is *not* copied.)

==========

13.14b: Does C have any Year 2000 problems?

A: No, although poorly-written C programs do.

The tm_year field of struct tm holds the value of the year minus
1900; this field will therefore contain the value 100 for the
year 2000. Code that uses tm_year correctly (by adding or
subtracting 1900 when converting to or from human-readable
4-digit year representations) will have no problems at the turn
of the millennium. Any code that uses tm_year incorrectly,
however, such as by using it directly as a human-readable
2-digit year, or setting it from a 4-digit year with code like

tm.tm_year = yyyy % 100; /* WRONG */

or printing it as an allegedly human-readable 4-digit year with
code like

printf("19%d", tm.tm_year); /* WRONG */

will have grave y2k problems indeed. See also question 20.32.

==========

13.24: I'm trying to port this A: Those functions are variously
old program. Why do I obsolete; you should
get "undefined external" instead:
errors for:

index? use strchr.
rindex? use strrchr.
bcopy? use memmove, after
interchanging the first and
second arguments (see also
question 11.25).
bcmp? use memcmp.
bzero? use memset, with a second
argument of 0.

==========

15.7: I have a pre-ANSI compiler, without stdarg.h. What can I do?

A: There's an older header, varargs.h, which offers about the
same functionality.

==========

18.5: How can I shut off the "warning: possible pointer alignment
problem" message which lint gives me for each call to malloc()?

A: The problem is that traditional versions of lint do not know,
and cannot be told, that malloc() "returns a pointer to space
suitably aligned for storage of any type of object." It is
possible to provide a pseudoimplementation of malloc(), using a
#define inside of #ifdef lint, which effectively shuts this
warning off, but a simpleminded definition will also suppress
meaningful messages about truly incorrect invocations. It may
be easier simply to ignore the message, perhaps in an automated
way with grep -v. (But don't get in the habit of ignoring too
many lint messages, otherwise one day you'll overlook a
significant one.)

C Interview Questions And Answers- 20

1.1: How do you decide which integer type to use?
---
1.1: How should I decide which integer type to use?
==========
float and double. None of the above rules apply if the address
of a variable is taken and must have a particular type.
---
float and double. None of the above rules apply if pointers to
the variable must have a particular type.
==========
1.4: What should the 64-bit type on a machine that can support it?
---
1.4: What should the 64-bit type be on a machine that can support it?
==========
The .c file containing the definition should also #include the
same header file, so that the compiler can check that the definition
---
same header file, so the compiler can check that the definition
matches the declarations.
==========
clear. The problem with the NODEPTR example is that the typedef
has not been defined at the point where the "next" field is
---
has not yet been defined at the point where the "next" field is
declared.
==========
1.21: How do I declare an array of N pointers to functions returning
pointers to functions returning pointers to characters?
---
1.21: How do I construct and understand declarations of complicated
types such as "array of N pointers to functions returning
pointers to functions returning pointers to char"?
==========
A: The first part of this question can be answered in at least
three ways:
---
A: There are at least three ways of answering this question:
==========
cdecl can also explain complicated declarations, help with
casts, and indicate which set of parentheses the arguments
---
casts, and indicate which set of parentheses the parameters
go in
==========
Any good book on C should explain how to read these complicated C
---
A good book on C should explain how to read these complicated
declarations "inside out" to understand them ("declaration
mimics use").
==========
1.30: What am I allowed to assume about the initial values
of variables which are not explicitly initialized?
---
of variables and arrays which are not explicitly initialized?
==========
A: Uninitialized variables with "static" duration (that is, those
declared outside of functions, and those declared with the
storage class static), are guaranteed to start out as zero,
---
storage class static), are guaranteed to start out as zero, just
as if the programmer had typed "= 0".
==========
A: Is the declaration of a static or non-local variable? Function
calls are allowed only in initializers for automatic variables
---
calls are allowed in initializers only for automatic variables
==========
A: A string literal can be used in two slightly different ways. As
an array initializer (as in the declaration of char a[]), it
---
an array initializer (as in the declaration of char a[] in the
question), it specifies the initial values of the characters in
that array.
==========
Anywhere else, it turns into an unnamed, static array of
characters, which may be stored in read-only memory,
which is why you can't safely modify it.
---
and which therefore cannot necessarily be modified.
==========
(For compiling old code, some compilers have a switch
controlling whether strings are writable or not.)
---
controlling whether string literals are writable or not.)
==========
When the name of a function appears in an expression like this,
---
When the name of a function appears in an expression,
it "decays" into a pointer (that is, it has its address
implicitly taken), much as an array name does.
==========
2.4: What's the best way of implementing opaque (abstract) data types
in C?
---
2.4: How can I implement opaque (abstract) data types in C?
==========
A: No. There is no single, good way for a compiler to implement
implicit structure comparison (i.e. to support the == operator
---
A: No. There is not a good way for a compiler to implement
structure comparison (i.e. to support the == operator
for structures) which is consistent with C's low-level flavor.
==========
A simple byte-by-byte comparison could founder on random bits
present in unused "holes" in the structure (such padding is used
to keep the alignment of later fields correct; see question 2.12).
---
present in unused "holes" in the structure (see question 2.12).
==========
Note also that if the structure contains any pointers, only
---
Also, if the structure contains any pointers, only
the pointer values will be written, and they are most unlikely
to be valid when read back in.
==========
Finally, note that for widespread portability you must use the
"b" flag when fopening the files; see question 12.38.
---
"b" flag when opening the files; see question 12.38.
==========
A: Structures may have this padding (as well as internal padding),
if necessary, to ensure that alignment properties will be
preserved when an array of contiguous structures is allocated.
Even when the structure is not part of an array, the end padding
---
A: Padding at the end of a structure may be necessary to preserve
alignment when an array of contiguous structures is allocated.
Even when the structure is not part of an array, the padding
remains, so that sizeof can always return a consistent size.
==========
A: At the present time, there is little difference. The C Standard
---
A: There is little difference. The C Standard
says that enumerations may be freely intermixed with other
integral types, without errors.
==========
that they obey block scope. (A compiler may also generate
nonfatal warnings when enumerations and integers are
indiscriminately mixed, since doing so can still be considered
bad style even though it is not strictly illegal.)
---
nonfatal warnings when enumerations are indiscriminately mixed,
since doing so can still be considered bad style.)
==========
(Loosely speaking, by "multiple, ambiguous side effects" we mean
any combination of ++, --, =, +=, -=, etc. in a single expression
---
any combination of increment, decrement, and assignment operators
in a single expression which causes the same object either to be
modified twice or modified and then inspected.
==========
Note that (long int)(a * b) would *not* have the desired effect.
---
Notice that (long int)(a * b) would *not* have the desired
effect.
==========
or a delibrate but nonstandard extension if a particular
---
or a deliberate but nonstandard extension if a particular
==========
Whenever possible, you should choose appropriate pointer types
in the first place, instead of trying to treat one type
---
When possible, however, you should choose appropriate pointer
types in the first place, rather than trying to treat one type
as another.
==========
void * acts as a generic pointer only because conversions are
---
void * acts as a generic pointer only because conversions (if
necessary) are applied automatically when other pointer types
are assigned to and from void *'s;
==========
4.12: I've seen different methods used for calling functions via
---
4.12: I've seen different syntax used for calling functions via
pointers. What's the story?
==========
pointers, and that "real" function names always decay implicitly
into pointers (in expressions, as they do in initializations;
see question 1.34). This reasoning (which is in fact used in
the ANSI standard) means that
---
see question 1.34). This reasoning means that
==========
function pointer followed by an argument list except call the
function pointed to.) An explicit * is still allowed.
---
function pointed to.)
==========
The ANSI C Standard essentially adopts the latter
interpretation, meaning that the explicit * is not required,
though it is still allowed.
==========
5.4: What is NULL and how is it #defined?
---
5.4: What is NULL and how is it defined?
==========
preprocessor macro NULL is #defined (by stdio.h and several
other headers) with the value 0, possibly cast to (void *)
---
preprocessor macro NULL is defined (by stdio.h and several
other headers) as a null pointer constant, typically 0 or
((void *)0)
==========
NULL should *only* be used for pointers; see question 5.9.
---
NULL should be used *only* as a pointer constant; see question 5.9.
==========
A: Not in general. The complication is that there are machines
---
A: Not in the most general case. The complication is that there
are machines which use different internal representations for
pointers to different types of data.
==========
pointer arguments of other types would still be problematical,
---
pointer arguments of other types could still (in the absence
of prototypes) be problematical,
==========
This article uses the phrase "null pointer" (in lower case) for
sense 1, the character "0" or the phrase "null pointer constant"
---
sense 1, the token "0" or the phrase "null pointer constant"
for sense 3, and the capitalized word "NULL" for sense 4.
==========
A: C programmers traditionally like to know more than they might
need to about the underlying machine implementation.
---
A: C programmers traditionally like to know a lot (perhaps more
than they need to) about the underlying machine implementation.
==========
integer zero instead of an error message, and if that uncast 0
was supposed to be a null pointer constant, the code may not
work.
---
was supposed to be a null pointer constant, the resulting
program may not work.
==========
Some 64-bit Cray machines represent int * in the lower 48 bits
of a word; char * additionally uses the upper 16 bits to
---
of a word; char * additionally uses some of the upper 16 bits to
indicate a byte address within a word.
==========
A: This message, which typically occurs with MS-DOS compilers, means
that you've written, via a null (perhaps because uninitialized)
pointer, to an invalid location (probably offset 0 in the
default data segment).
---
means that you've written, via a null pointer, to an invalid
location -- probably offset 0 in the default data segment.
==========
A: In one source file you defind an array of characters and in the
---
A: In one source file you defined an array of characters and in the
==========
It is important to realize that a reference like x[3] generates
---
It is useful to realize that a reference like x[3] generates
different code depending on whether x is an array or a pointer.
==========
If you can't use C9X or gcc, you'll have to use malloc(), and
---
If you can't use C99 or gcc, you'll have to use malloc(), and
remember to call free() before the function returns.
==========
Finally, in C9X you can use a variable-length array.
---
Finally, in C99 you can use a variable-length array.
==========
A: The rule (see question 6.3) by which arrays decay into pointers
is not applied recursively.
---
is *not* applied recursively.
==========
not provide an automatically-managed string type. C compilers
only allocate memory for objects explicitly mentioned in the
---
allocate memory only for objects explicitly mentioned in the
source code (in the case of strings, this includes character
==========
A: You got lucky, I guess. The memory pointed to by the
unitialized pointer p happened to be writable by you,
---
A: You got lucky, I guess. The memory randomly pointed to by
the uninitialized pointer p happened to be writable by you,
==========
A pointer value which has been freed is, strictly speaking,
invalid, and *any* use of it, even if is not dereferenced,
---
invalid, and *any* use of it, even if it is not dereferenced,
can theoretically lead to trouble,
==========
A: In C, characters are represented by small integers corresponding
to their values (in the machine's character set), so you
---
to their values in the machine's character set. Therefore, you
don't need a conversion function: if you have the character, you
have its value.
==========
DEBUG("i = %d" _ i)
---
DEBUG("i = %d" _ i);
==========
controversial trigraph sequences). The ANSI C standard also
formalizes the C run-time library support routines.
---
formalized the C run-time library support routines.

C Interview Questions And Answers- 19

[Q19.1 How can I read a single character from the keyboard...]

Note that the answers are often not unique even across different
variants of a system; bear in mind when answering system-
---
Note that the answers may differ even across variants of
otherwise similar systems (e.g. across different variants of
Unix); bear in mind when answering system-specific questions
that the answer that applies to your system may not apply to
everyone else's.

==========

[Q19.3 How can I display a percentage-done indication...]

current line. The character '\b' is a backspace, and will
usually move the cursor one position to the left.
---
usually move the cursor one position to the left. (But remember
to call fflush(), too.)

==========

[Q19.8 How can I direct output to the printer?]

Under some circumstances, another (and perhaps the only)
possibility is to use a window manager's screen-capture
function, and print the resulting bitmap.

==========

[Q19.10 How can I do graphics?]

A modern, platform-independent graphics library (which also
supports 3D graphics and animation) is OpenGL. Other graphics
standards which may be of interest are GKS and PHIGS.

==========

[Q19.12 How can I find out the size of a file, prior to reading it in?]

You can fseek() to the end and then use
ftell(), or maybe try fstat(), but these tend to have the same
sorts of 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
---
to return a byte count except for binary files (but, strictly
speaking, binary files don't necessarily support fseek to
SEEK_END at all). Some systems provide functions called
filesize() or filelength(), but these are obviously not
portable, either.

==========

[Q19.20 How can I read a directory in a C program?]

(MS-DOS also has FINDFIRST and FINDNEXT routines which
do essentially the same thing.)
---
do essentially the same thing, and MS Windows has FindFirstFile
and FindNextFile.)

==========

[Q19.23 How can I allocate arrays or structures bigger than 64K?]

to allocate huge amounts of it contiguously. (The C Standard
does not guarantee that single objects can be 32K or larger,
or 64K for C9X.) Often it's a good idea to use data
---
or 64K for C99.) Often it's a good idea to use data

==========

[Q19.25 How can I access memory (a memory-mapped device...]

Then, *magicloc refers to the location you want.
---
Then, *magicloc refers to the location you want. If the
location is a memory-mapped I/O register, you will probably also
want to use the volatile qualifier.

==========

[Q19.27 How can I invoke another program...]

Depending on your operating system, you may also be able to use
system calls such as exec or spawn (or execl, execv, spawnl,
spawnv, etc.).

==========

[Q19.37 How can I implement a delay... with sub-second resolution?]

A: Unfortunately, there is no portable way. V7 Unix, and derived
systems, provided a fairly useful ftime() function with
resolution up to a millisecond, but it has disappeared from
System V and POSIX. Other routines you might look for on your
---
A: Unfortunately, there is no portable way. Routines you might
look for on your system include clock(), delay(), ftime(),
gettimeofday(), msleep(), nap(), napms(), nanosleep(),
setitimer(), sleep(), Sleep(), times(), and usleep().

==========

[Q19.40 How do I... Use sockets? Do networking?]

and W. R. Stevens's _UNIX Network Programming_. There is also
plenty of information out on the net itself, including the
"Unix Socket FAQ" at http://kipper.york.ac.uk/~vic/sock-faq/
---
"Unix Socket FAQ" at http://www.developerweb.net/sock-faq/

and "Beej's Guide to Network Programming" at
http://www.ecst.csuchico.edu/~beej/guide/net/.

(One tip: depending on your OS, you may need to explicitly
request the -lsocket and -lnsl libraries; see question 13.25.)

==========

[Q20.14 Are pointers really faster than arrays?]

It is "usually" faster to march through large arrays with
---
For conventional machines, it is usually faster to march through
large arrays with pointers rather than array subscripts, but for
some processors the reverse is true.

==========

[Q20.20 Why don't C comments nest? ...]

Note also that // comments, as in C++, are not yet legal in C,
so it's not a good idea to use them in C programs (even if your
compiler supports them as an extension).
---
Note also that // comments have only become legal in C as of
C99.

==========

20.20b: Is C a great language, or what? Where else could you write
---
20.21b: Is C a great language, or what? Where else could you write
something like a+++++b ?

==========

[Q20.27 ... Can I use a C++ compiler to compile C code?]

compilation modes. See also questions 8.9 and 20.20.
---
compilation modes. (But it's usually a bad idea to compile
straight C code as if it were C++; the languages are different
enough that you'll generally get poor results.) See also
questions 8.9 and 20.20.

==========

20.32: Will 2000 be a leap year? Is (year % 4 == 0) an accurate test
for leap years?
---
20.32: Is (year % 4 == 0) an accurate test for leap years? (Was 2000 a
leap year?)

A: Yes and no, respectively. The full expression for the present
Gregorian calendar is
---
A: No, it's not accurate (and yes, 2000 was a leap year).
The full expression for the present Gregorian calendar is

==========

[Q20.34 ...how do you write a program which produces its own source code...?]

(This program, like many of the genre, neglects to #include
stdio.h, and assumes that the double-quote character " has the
---
(This program has a few deficiencies, among other things
neglecting to #include stdio.h, and assuming that the double-
quote character " has the value 34, as it does in ASCII.)

Here is an improved version, posted by James Hu:

#define q(k)main(){return!puts(#k"\nq("#k")");}
q(#define q(k)main(){return!puts(#k"\nq("#k")");})

==========

[Q20.35 What is "Duff's Device"?]

A: It's a devastatingly deviously unrolled byte-copying loop,
devised by Tom Duff while he was at Lucasfilm. In its "classic"
form, it looks like:
---
A: It's a devastatingly devious way of unrolling a loop, devised by
Tom Duff while he was at Lucasfilm. In its "classic" form, it
was used to copy bytes, and looked like this:

==========

[Q20.38 Where does the name "C" come from, anyway?]

A: C was derived from Ken Thompson's experimental language B, which
was inspired by Martin Richards's BCPL (Basic Combined
Programming Language), which was a simplification of CPL
(Cambridge Programming Language).
---
(Combined Programming Language, or perhaps Cambridge Programming
Language).

==========

[Q20.40 Where can I get extra copies of this list?]

What about back issues?

This list is an evolving document containing questions which
have been Frequent since before the Great Renaming; it is not
just a collection of this month's interesting questions. Older
copies are obsolete and don't contain much, except the
occasional typo, that the current list doesn't.


C Interview Questions And Answers- 18

[Q2.14 How can I determine the byte offset of a field within a structure?]

A: ANSI C defines the offsetof() macro, which should be used if
available; see stddef.h. If you don't have it, one possible
implementation is
---
A: ANSI C defines the offsetof() macro in stddef.h, which lets
you compute the offset of field f in struct s as
offsetof(struct s, f). If for some reason you have to code this
sort of thing yourself, one possibility is

==========

[2.15 How can I access structure fields by name at run time?]

A: Build a table of names and offsets, using the offsetof() macro.
The offset of field b in struct a is

offsetb = offsetof(struct a, b)

If structp is a pointer to an instance of this structure, and
field b is an int (with offset as computed above), b's value can
be set indirectly with
---
A: Keep track of the field offsets as computed using the offsetof()
macro (see question 2.14). If structp is a pointer to an
instance of the structure, and field f is an int having offset
offsetf, f's value can be set indirectly with

==========

[Q2.20 Can I initialize unions?]

A: The current C Standard allows an initializer for the first-named
member of a union. C9X will introduce "designated initializers"
which can be used to initialize any member.
---
A: In the original ANSI C, an initializer was allowed only for the
first-named member of a union. C99 introduces "designated
initializers" which can be used to initialize any member.

==========

[Q3.2 Under my compiler... Regardless of the order of evaluation...]

example, the compiler chose to multiply the previous value by
itself and to perform both increments afterwards.
---
itself and to perform both increments later.

[Q3.8 How can I understand these complex expressions?]

The second sentence can be difficult to understand. It says
that if an object is written to within a full expression, any
and all accesses to it within the same expression must be for
the purposes of computing the value to be written. This rule
effectively constrains legal expressions to those in which the
accesses demonstrably precede the modification.
---
and all accesses to it within the same expression must be
directly involved in the computation of the value to be written.
This rule effectively constrains legal expressions to those in
which the accesses demonstrably precede the modification. For
example, i = i + 1 is legal, but not a[i] = i++ (see question
3.1).

==========

[3.9 So... we don't know which..., but i does get incremented..., right?]

A: *No*. Once an expression or program becomes undefined, *all*
---
A: Not necessarily! Once an expression or program becomes
undefined, *all* aspects of it become undefined.

==========

[Q4.2 I'm trying to declare a pointer and allocate some space for it...]

A: The pointer you declared is p, not *p. To make a pointer point
somewhere, you just use the name of the pointer:
---
A: The pointer you declared is p, not *p. When you're manipulating
the pointer itself (for example when you're setting it to make
it point somewhere), you just use the name of the pointer:

==========

[4.3 Does *p++ increment p, or what it points to?]

A: Postfix ++ essentially has higher precedence than the prefix
---
A: The postfix ++ and -- operators essentially have higher
precedence than the prefix unary operators.

==========

[Q4.10 ...How can I pass a constant by reference?]

A: You can't do this directly. You will have to declare
---
A: In C99, you can use a "compound literal":

f((int[]){5});

Prior to C99, you couldn't do this directly; you had to declare
a temporary variable, and then pass its address to the function:

==========

[Q5.6 If NULL were defined as follows...]

At any rate, ANSI function prototypes ensure that most (though
not quite all; see question 5.2) pointer arguments are converted
correctly when passed as function arguments, so the question is
largely moot.

==========

5.20: What does a run-time "null pointer assignment" error mean?
How can I track it down?

A debugger may let you set a data watchpoint on location 0.
Alternatively, you could write a bit of code to stash away a
copy of 20 or so bytes from location 0, and periodically check
that the memory at location 0 hasn't changed. See also question
16.8.

==========

[Q6.15 How can I declare local arrays of a size matching a passed-in array?]

A: Until recently, you couldn't. Array dimensions in C
traditionally had to be compile-time constants. C9X will
introduce variable-length arrays (VLA's) which will solve this
---
A: Until recently, you couldn't; array dimensions in C
traditionally had to be compile-time constants. However, C99
introduces variable-length arrays (VLA's) which solve this
problem; local arrays may have sizes set by variables or other
expressions, perhaps involving function parameters.

==========

[Q6.16 How can I dynamically allocate a multidimensional array?]

You can also use sizeof(*array1) and sizeof(**array1)
instead of sizeof(int *) and sizeof(int).)

==========

[Q6.19 How do I write functions which accept two-dimensional arrays...]

C9X will allow variable-length arrays, and once compilers which
accept C9X's extensions become widespread, this will probably
---
C99 allows variable-length arrays, and once compilers which
accept C99's extensions become widespread, VLA's will probably
become the preferred solution.

==========

[Q7.27 So can I query the malloc package to find out how big...]

(Some compilers provide nonstandard extensions.)

==========

[Q7.32 What is alloca() and why is its use discouraged?]

Now that C99 supports variable-length arrays (VLA's),
they can be used to more cleanly accomplish most of the
tasks which alloca() used to be put to.

==========

[Q8.6 How can I get the numeric (character set) value corresponding to...]

To convert back and forth between the digit characters and the
corresponding integers in the range 0-9, add or subtract the
constant '0' (that is, the character value '0').

==========

[Q10.7 Is it acceptable for one header file to #include another?]

the prestigious Indian Hill Style Guide (see question 17.9)
disparages them; they can make it harder to find relevant
definitions; they can lead to multiple-definition errors if a file
is #included twice;
---
is #included twice; they can lead to increased compilation time;
and they make manual Makefile maintenance very difficult.

==========

10.11: I seem to be missing the system header file sgtty.h.
Can someone send me a copy?
---
10.11: I'm compiling a program, and I seem to be missing one of the
header files it requires. Can someone send me a copy?

A: There are several situations, depending on what sort of header
file it is that's "missing".

If the missing header file is a standard one, there's a problem
with your compiler. You'll need to contact your vendor, or
someone knowledgeable about your particular compiler, for help.

The situation is more complicated in the case of nonstandard
headers. Some are completely system- or compiler-specific.
Some are completely unnecessary, and should be replaced by their
Standard equivalents. (For example, instead of malloc.h, use
stdlib.h.) Other headers, such as those associated with
popular add-on libraries, may be reasonably portable.

Standard headers exist in part so that definitions appropriate
to your compiler, operating system, and processor can be
supplied. You cannot just pick up a copy of someone else's
header file and expect it to work, unless that person is using
exactly the same environment. Ask your compiler vendor why the
file was not provided (or to send a replacement copy).
---
exactly the same environment. You may actually have a
portability problem (see section 19), or a compiler problem.
Otherwise, see question 18.16.

==========

[Q10.26 How can I write a macro which takes a variable number of arguments?]

C9X will introduce formal support for function-like macros with
variable-length argument lists. The notation ... will appear at
---
C99 introduces formal support for function-like macros with
variable-length argument lists. The notation ... can appear at

definition will be replaced by the variable arguments during
---
definition is replaced by the variable arguments during

==========

[Q11.1 What is the "ANSI C Standard?"]

More recently, the Standard has been adopted as an international
standard, ISO/IEC 9899:1990, and this ISO Standard replaces the
earlier X3.159 even within the United States (where it is known
---
A year or so later, the Standard was adopted as an international
standard, ISO/IEC 9899:1990, and this ISO Standard replaced the
earlier X3.159 even within the United States (where it was known

As of this writing, a complete revision of the Standard is in
its final stages. The new Standard is nicknamed "C9X" on the
assumption that it will be finished by the end of 1999. (Many
of this article's answers have been updated to reflect new C9X
features.)
---
Most recently, a major revision of the Standard, "C99", has been
completed and adopted.

The original ANSI Standard included a "Rationale," explaining
many of its decisions, and discussing a number of subtle points,
including several of those covered here. (The Rationale was
"not part of ANSI Standard X3.159-1989, but... included for
information only," and is not included with the ISO Standard.
A new one is being prepared for C9X.)
---
Several versions of the Standard, including C99 and the original
ANSI Standard, have included a "Rationale," explaining many of
its decisions, and discussing a number of subtle points,
including several of those covered here.

==========

[Q11.2 How can I get a copy of the Standard?]

Note that ANSI derives revenues to support its operations
from the sale of printed standards, so electronic copies
are *not* available.
---
An electronic (PDF) copy is available on-line, for US$18,
from www.ansi.org.

The last time I checked, the cost was $130.00 from ANSI or
$400.50 from Global. Copies of the original X3.159 (including
the Rationale) may still be available at $205.00 from ANSI or
$162.50 from Global.

In the U.S., it may be possible to get a copy of the original
ANSI X3.159 (including the Rationale) as "FIPS PUB 160" from

National Technical Information Service (NTIS)
U.S. Department of Commerce
Springfield, VA 22161
703 487 4650

==========

[Q11.10 Why can't I pass a char ** to a function which expects...]

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.
---
If you must assign or pass pointers which have qualifier
mismatches at other than the first level of indirection, you
must use explicit casts (e.g. (const char **) in this case),
although as always, the need for such a cast may indicate a
deeper problem which the cast doesn't really fix.

==========

11.27: Why does the ANSI Standard not guarantee more than six case-
insensitive characters of external identifier significance?
---
11.27: Why does the ANSI Standard place limits on the length and case-
significance of external identifiers?

The limitation is only that identifiers be *significant*
in the first six characters, not that they be restricted to
six characters in length. This limitation is marked in the
Standard as "obsolescent", and will be removed in C9X.
---
in some initial sequence of characters, not that they be
restricted to that many characters in total length.
(The limitation was to six characters in the original
ANSI Standard, but has been relaxed to 31 in C99.)

==========

[Q11.33 ...implementation-defined, unspecified, and undefined behavior.]

(A fourth defined class of not-quite-precisely-defined behavior,
without the same stigma attached to it, is "locale-specific".)

==========

[Q12.2 Why does the code... copy the last line twice?]

Usually, you should just check the return value of
the input routine (in this case, fgets() will return NULL on end-
of-file); often, you don't need to use feof() at all.
---
the input routine -- fgets(), for example, returns NULL on end-
of-file. In virtually all cases, there's no need to use feof()
at all.

==========

[Q12.21 How can I tell how much... buffer space... for a... sprintf call?]

The "obvious" solution to the overflow problem is a length-
limited version of sprintf(), namely snprintf(). It would be
used like this:
---
To avoid the overflow problem, you can use a length-limited
version of sprintf(), namely snprintf(). It is used like this:

It will be standardized in C9X.
---
It has finally been standardized in C99.

When the C9X snprintf() arrives, it will also be possible to use
it to predict the size required for an arbitrary sprintf() call.
C9X snprintf() will return the number of characters it would
have placed in the buffer, not just how many it did place.
Furthermore, it may be called with a buffer size of 0 and a
null pointer as the destination buffer. Therefore, the call
---
As an extra, added bonus, the C99 snprintf() provides a way
to predict the size required for an arbitrary sprintf() call.
C99's snprintf() returns the number of characters it would have
placed in the buffer, and it may be called with a buffer size
of 0. Therefore, the call

will compute the number of characters required for the fully-
---
predicts the number of characters required for the fully-

Yet another option is the (nonstandard) asprintf() function,
present in various C libraries including bsd's and GNU's, which
formats to (and returns a pointer to) a malloc'ed buffer, like
this:

char *buf;
asprintf(&buf, "%d = %s", 42, "forty-two");
/* now buf points to malloc'ed space containing formatted string */

==========

[Q12.23 Why does everyone say not to use gets()?]

A: Unlike fgets(), gets() cannot be told the size of the buffer
it's to read into, so it cannot be prevented from overflowing
that buffer. As a general rule, always use fgets().
---
that buffer. The Standard fgets() function is a vast
improvement over gets(), although it's not perfect, either.
(If long lines are a real possibility, their proper handling
must be carefully considered.)

==========

12.26: How can I flush pending input so that a user's typeahead isn't
---
12.26b: If fflush() won't work, what can I use to flush input?

There is no standard way to discard unread characters from a
stdio input stream, nor would such a way necessarily be
sufficient, since unread characters can also accumulate in
other, OS-level input buffers. You may be able to read and
discard characters until \n, or use the curses flushinp()
function, or use some system-specific technique. See also
questions 19.1 and 19.2.
---
other, OS-level input buffers. If you're trying to actively
discard typed-ahead input (perhaps in anticipation of issuing a
critical prompt), you'll have to use a system-specific
technique; see questions 19.1 and 19.2.

==========

[Q12.30 I'm trying to update a file in place...]

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.
---
truncate the file at that point, and that you may have to
preserve line lengths. See also question 19.14.

==========

[Q12.34 Once I've used freopen(), how can I get the original stdout... back?]

It is barely possible to save away information about a stream
before calling freopen(), such that the original stream can
later be restored, but the methods involve system-specific calls
such as dup(), or copying or inspecting the contents of a FILE
structure, which is exceedingly nonportable and unreliable.
---
It may be possible, in a nonportable way, to save away
information about a stream before calling freopen(), such that
the original stream can later be restored. One way is to use a
system-specific call such as dup() or dup2(), if available.
Another is to copy or inspect the contents of the FILE
structure, but this is exceedingly nonportable and unreliable.

==========

12.36b: How can I arrange to have output go two places at once,
e.g. to the screen and to a file?

Here is a simple example:

#include stdio.h
#include stdarg.h

void f2printf(FILE *fp1, FILE *fp2, char *fmt, ...)
{
va_list argp;
va_start(argp, fmt); vfprintf(fp1, fmt, argp); va_end(argp);
va_start(argp, fmt); vfprintf(fp2, fmt, argp); va_end(argp);
}

where f2printf() is just like fprintf() except that you give it
two file pointers and it prints to both of them.

==========

[Q13.2 Why does strncpy() not always place a '\0' terminator...]

You can get around the problem by using strncat() instead
of strncpy(): if the destination string starts out empty
(that is, if you do *dest = '\0' first), strncat()
does what you probably wanted strncpy() to do.

==========

[Q13.12 How can I get the current date or time of day in a C program?]

printf("It's %.24s.\n", ctime(&now));
---
printf("It's %s", ctime(&now));

If you need control over the format, use strftime().
If you need sub-second resolution, see question 19.37.

==========

[Q13.14 How can I add N days to a date?]

A: The ANSI/ISO Standard C mktime() and difftime() functions
provide some support for both problems.
---
provide some (limited) support for both problems.

These solutions are only guaranteed to work correctly
---
However, these solutions are guaranteed to work correctly only
for dates in the range which can be represented as time_t's.

(For conservatively-sized time_t, that range is often -- but not
always -- from 1970 to approximately 2037; note however that
there are time_t representations other than as specified by Unix
and Posix.)

Another approach to both problems,
which will work over a much wider range of dates,
is to use "Julian day numbers".

==========

[Q13.15 I need a random number generator.]

If you do find yourself needing to implement your own random
number generator, there is plenty of literature out there; see
the References. There are also any number of packages on the
net: look for r250, RANLIB, and FSULTRA (see question 18.16).
---
the References below or the sci.math.num-analysis FAQ list.
There are also any number of packages on the net: old standbys
are r250, RANLIB, and FSULTRA (see question 18.16), and there is
much recent work by Marsaglia, and Matumoto and Nishimura (the
"Mersenne Twister"), and some code collected by Don Knuth on his
web pages.

==========

[Q13.17 Each time I run my program, I get the same sequence of numbers...]

A: You can call srand() to seed the pseudo-random number generator
with a truly random initial value. Popular seed values are the
time of day, or the elapsed time before the user presses a key
(although keypress times are hard to determine portably;
---
with a truly random (or at least variable) initial value, such
as the time of day. Here is a simple example:

#include stdlib.h
#include time.h

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

(Unfortunately, this code isn't perfect -- among other things,
the time_t returned by time() might be a floating-point type,
hence not portably convertible to unsigned int without the
possibility of overflow.

==========

[Q14.1 When I set a float... 3.1, why is printf printing it as 3.0999999?]

A: Most computers use base 2 for floating-point numbers as well as
for integers. In base 2, one divided by ten is an infinitely-
repeating fraction (0.0001100110011...), so fractions such as
3.1 (which look like they can be exactly represented in decimal)
---
for integers. Although 0.1 is a nice, polite-looking fraction
in base 10, its base-2 representation is an infinitely-repeating
fraction (0.0001100110011...), so exact decimal fractions such as 3.1
cannot be represented exactly in binary.

[Q14.3 ...I keep getting "undefined: sin" compilation errors.]

A: Make sure you're actually linking with the math library. For
instance, under Unix, you usually need to use the -lm option, at
---
instance, due to a longstanding bug in Unix and Linux systems,
you usually need to use an explicit -lm flag, at the *end* of
the command line, when compiling/linking.

==========

[Q14.5 What's a good way to check for "close enough" floating-point equality?]

use something like

#include math.h
if(fabs(a - b) = epsilon * fabs(a))

for some suitably-chosen degree of closeness epsilon (as long as
a is nonzero!).
---
where epsilon is a value chosen to set the degree of "closeness"
(and where you know that a will not be zero).

==========

[Q14.8 The predefined constant M_PI seems to be missing...]
machine's copy of math.h.

If you need pi, you'll have to define it yourself, or compute it
with 4*atan(1.0).
---
with 4*atan(1.0) or acos(-1.0).

==========

[Q14.9 How do I test for IEEE NaN and other special values?]

C9X will provide isnan(), fpclassify(), and several other
---
C99 provides isnan(), fpclassify(), and several other
classification routines.

==========

[Q14.11 What's a good way to implement complex numbers in C?]

C9X will support complex as a standard type.
---
C99 supports complex as a standard type.

==========

[Q15.6 How can I write a function analogous to scanf()...]

A: C9X will support vscanf(), vfscanf(), and vsscanf().
(Until then, you may be on your own.)
---
A: C99 (but *not* any earlier C Standard) supports vscanf(),
vfscanf(), and vsscanf().

==========

[Q16.1b I'm getting baffling syntax errors which make no sense at all...]

A: Check for unclosed comments or mismatched #if/#ifdef/#ifndef/
#else/#endif directives; remember to check header files, too.
---
A: Check for unclosed comments, mismatched #if/#ifdef/#ifndef/
#else/#endif directives, and perhaps unclosed quotes; remember
to check header files, too.

My Ad

.