of it learned that they were probably not cut out for graduate school. It was a week of
furious activity, in which I learned more about APL and Lisp than I have done in the dozen
years before or since.
[1] You can see why they don't have an "Obfuscated APL Competition" —there's no need, it
already comes that way
How Is a File Descriptor Different from a File Pointer?
This question follows naturally from the previous one. All the UNIX routines that manipulate files use
either a file pointer or a file descriptor to identify the file they are operating on; what are each of these,
and when is each used? The answer is actually straightforward, and gives you an idea of how familiar
a person is with UNIX I/O and the various trade-offs.
All the system calls that manipulate files take (or return) a "file descriptor" as an argument. "File
descriptor" is somewhat of a misnomer; the file descriptor is a small integer (usually between 0 and
255) used in the Sun implementation to index into the per-process table-of-open-files. The system I/O
calls are creat(), open(), read(), write(), close(), ioctl(), and so on, but these
are not a part of ANSI C, won't exist in non-UNIX environments, and will destroy program portability
if you use them. Hence, a set of standard I/O library calls were specified, which ANSI C now requires
all hosts to support.
To ensure program portability, use the stdio I/O calls fopen(), fclose(), putc(),
fseek()—most of these routine names start with "f". These calls take a pointer to a FILE structure
(sometimes called a stream pointer) as an argument. The FILE pointer points to a stream structure,
defined in <stdio.h>. The contents of the structure vary from implementation to implementation, and
on UNIX is typically an entry in the per-process table-of-open-files. Typically, it contains the stream
buffer, all the necessary variables to indicate how many bytes in the buffer are actual file data, flags to
indicate the state of the stream (like ERROR and EOF), and so on.
- So a file descriptor is the offset in the per-process table-of-open-files (e.g., "3"). It is used in a
UNIX system call to identify the file. - A FILE pointer holds the address of a file structure that is used to represent the open I/O
stream (e.g. hex 20938). It is used in an ANSI C stdio library call to identify the file.
The C library function fdopen() can be used to create a new FILE structure and associate it with the
specified file descriptor (effectively converting between a file descriptor integer and the corresponding
stream pointer, although it does generate an additional new entry in the table-of-open-files).
Write Some Code to Determine if a Variable Is Signed or Not
One colleague, interviewing with Microsoft, was asked to "write some code to determine if a variable
is signed or not." It is actually a pretty tough question because it leaves too much open to
interpretation. Some people wrongly equate "signed" with "has a negative sign" and assume that what
is wanted is a trivial function or macro to say if a value is less than zero.
That isn't it. The question has to do with whether or not a given type is signed or unsigned in a
particular implementation. In ANSI C, "char" can be either signed or unsigned as an implementation
desires. It is useful to know which when writing code that will be ported to many platforms, and
ideally the result will be a compiletime constant.