Path: utzoo!utgpu!news-server.csri.toronto.edu!rpi!bu.edu!snorkelwacker.mit.edu!bloom-picayune.mit.edu!eddie.mit.edu!uunet!blunderbuss!itnay!ickerpay!etiquette From: emily@etiquette.uu.net (Emily Postnews) Newsgroups: comp.lang.c Subject: New 'n' Improved comp.lang.c FAQ List Message-ID: <910401.0xf001@etiquette.uu.net> Date: 1 Apr 91 05:00:00 GMT Expires: 3 Apr 91 00:00:00 GMT Sender: scs@etiquette.uu.net (Strictly Correct Software) Organization: Usenet Proper Behavior Department Lines: 175 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.