New 'n' Improved comp.lang.c FAQ List

Emily Postnews emily at etiquette.uu.net
Mon Apr 1 15:00:00 AEST 1991


                Emily Postnews Answers Your C Questions


The previous editor of this feature was an old curmudgeon with no sense
of humor and a number of decidedly conservative, old-fashioned notions
about C programming.  Therefore, the management has hired me, Emily
Postnews, noted Usenetiquette authority, to give you the answers you
want to hear.

In preparation, I have spent the last two months learning C on a PC-XT
with the highly-recommended Rotifer-C compiler.  I can see why you are
all so enamored of C; it's quite a language!  Let's begin.

                                 ------

Q: Why is the null pointer zero?

A: This is a common misconception.  In fact, the null pointer is
really 1.  This convention arose because of the PDP-11's efficient
predecrement addressing mode (which also explains why the stack grows
down).  When you pass a 1 as a null pointer, the correct internal value
(0) results after the autodecrement.

                                 ------

Q: Why doesn't this function work:

        itoa(int i)
        {
        char retbuf[5];         /* biggest int: 32769 */
        sprintf("%d", retbuf, i);
        return retbuf;
        }

A: Heavens, you left out the parentheses in the return statement.
No wonder it didn't work.

                                 ------

Q: My compiler complains when I try to add a pointer-to-int and a
pointer-to-double.

A: If ip is the pointer-to-int and dp is the pointer-to-double, you can
add them with the expression

        (double *)(int *)((int)*(char *)ip * sizeof(int) +
                                (int)*(char *)dp * sizeof(double))

You may have to reverse the leading (int *) and (double *) casts,
depending on what you want to do with the result.

You have to do the pointer scaling (multiply by sizeof int and double)
yourself, because compilers are generally too inadequate to figure out
how to do it themselves.  Sometimes we have to put up with these
annoying little inconsistencies in the language.

                                 ------

Q: I just typed in a sample program from Ed Bourbon's new book, Boffo C
Primer Triple Plus.  When I run the program, I get an annoying extra
blank line before the first prompt.  The prompts are printed with
something like

        printf("\nenter your shoe size: ");

What's going on?

A: That blank line must be coming from the previous program you ran.
The operating system, MS-DOS, automatically prints a blank line after
every program runs.  Therefore, programs should not print the last
newline themselves.  If one erroneously does, the extra newline stays in
the output buffer and ends up at the beginning of the next program.

You can fix this by clearing the buffer, when your program starts, with
the line

        fflush(stdout);

If you are using an ANSI Standard C compiler, use

        fflush(__STDOUT__);

instead, for compatibility.

                                 ------

Q: The other FAQ list recommended avoiding alloca.  What's wrong
with it?

A: That "other FAQ list" contained numerous examples of unnecessarily
pessimistic advice.  alloca neatly solves several problems which have no
other solution, and it is trivial to implement: it need only adjust the
stack pointer.  It was utter spinelessness on X3J11's part that alloca
was not adopted in the C Standard.  Go ahead and use it; any responsible
vendor will provide it as an extension.

                                 ------

Q: What's the best indentation and brace placement style?

A: Don't bother indenting; the compiler ignores whitespace anyway.
Braces epitomize the cryptic terseness for which C is notorious.  Rather
than trying to place them in such a way as to make grouping more
obvious, it is better to set up some macro #definitions:

        #define begin {
        #define end   }

Then you can use the keywords "begin" and "end" to delineate compound
statements, which will make things much clearer.

Using the preprocessor to provide "syntactic syrup" in this way can
powerfully affect the readability of a program.  I'm sure that many
readers have come up with other syntax-liberating macros (SLM's) like
these.  Why doesn't everybody post their favorite ones, and we'll
compile a complete list?

                                 ------

Q: What does "undefined order of evaluation" mean?  Why is it to be
avoided?

A: Warnings about depending upon machine-dependent evaluation order
apply only to naive, uneducated users who are not as intimately familiar
with your machine as you are.  Since you know what order your compiler
evaluates things in, you should go ahead and make use of it.  Doing so
will probably make your programs more efficient, too.

                                 ------

Q: Which is more efficient, i = i + 1 or i = 1 + i ?

A: Neither; both will generate a two- or three-operand add instruction,
with a wasteful in-line immediate constant operand, while most machines
have a much more efficient single-operand increment instruction.  My
compiler lets me use the built-in intrinsic function __inc(i) so that
the inc instruction is emitted in-line, without even using a function
call!  If your compiler doesn't have __inc(), you might have to use an
asm directive.

                                 ------

Q: How can I call interpreted BASIC from C?

A: Just shove the function call onto the input stream using the TIOCSTI
ioctl, then jump to the interpreter with system() or exec().

                                 ------

Q: How can I find out the time of day when I'm writing a C program?

A: Look at your watch, silly.

                                 ------

Q: The microprocessor in the electronic toaster I'm writing the firmware
for has a quirk: if you read a register within 3.14 microseconds of
writing it, it is cleared.  The hardware designers figured there was no
reason to operate the toaster for 0 seconds, so they arranged that a
value of 0 in the timer register turns the heating element on
indefinitely.

Last week I hand-optimized the user interface code, which sped things up
enough that some of the register accesses are coming too close on the
heels of the previous store.  The prototype toaster at my bench keeps
bursting into flames, and my co-workers are starting to complain about
the smoke.  Is there a C keyword, sort of like volatile, which will keep
the compiler from emitting code to read a value within 3.14 microseconds
of writing it?

A: Why are you posting this to comp.lang.c?  The ANSI C Standard
contains language specifically discussing embedded applications, and
distinguishes between "toasted" and "non-toasted" implementations.  Post
your question to comp.std.c, instead.



More information about the Comp.lang.c mailing list