scs@adam.mit.edu (Steve Summit) (06/01/90)
46c47,49 < Both exist in several editions. --- > Both exist in several editions. Andrew Koenig's book _C Traps and > Pitfalls_ also covers many of the difficulties frequently discussed > here. 72,73c75,76 < Send your comments to scs@adam.mit.edu, disregarding the From: line in < this article's header, which may be incorrect. --- > Send your comments to scs@adam.mit.edu and/or scs%adam.mit.edu@mit.edu; > this article's From: line may be incorrect. 82,87c85,91 < a special value -- "null" -- which is distinguishable from all other < pointer values and which is not the address of any object. That is, < the address-of operator & will never "return" null, nor will malloc. < Note that there is a null pointer for each pointer type, and that < different pointer types (e.g. char * and int *) may have _different_ < null pointers. --- > a special value -- the "null pointer" -- which is distinguishable > from all other pointer values and which is not the address of any > object. That is, the address-of operator & will never "return" a > null pointer, nor will a successful call to malloc. (malloc returns > 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.") 88a93,106 > Although a null pointer does not "point anywhere," it is different > from an uninitialized pointer, about which we cannot say where it > points. A null pointer points explicitly nowhere (i.e. not at any > object); an uninitialized pointer might point anywhere (at some > random object, or at a garbage or unallocated address). See also > question 29. > > As mentioned in the definition above, there is a null pointer for > each pointer type, and the internal values of null pointers for > different types may be different. Although programmers need not > know the internal values, the compiler must always be informed which > null pointer is required, so it can make the distinction if > necessary (see below). 150c169,171 < apply to pointers to functions. --- > apply to pointers to functions. (Any object pointer may be cast to > the "universal" pointer type void *, or char * under a pre-ANSI > compiler, when heterogeneous pointers must be passed around.) 169,171c191,194 < doing so sends the wrong stylistic message. In particular, do not < use NULL when the ASCII nul character is desired. Provide your own < definition --- > doing so sends the wrong stylistic message. (The ANSI #definition > of NULL is allowed to be (void *)0, which will not work in non- > pointer contexts.) In particular, do not use NULL when the ASCII > nul character is desired. Provide your own definition 183,186c207,209 < A: Until now, no mention has been made of the internal representation < of the null pointer. Programmers should never need to know the < details of this representation, because it is normally taken care of < by the compiler. If a machine uses a nonzero bit pattern for null --- > A: Programmers should never need to know the internal representation(s) > of null pointers, because they are normally taken care of by the > compiler. If a machine uses a nonzero bit pattern for null 287a315,332 > When the phrase "null pointer" is casually used, one of three things > may be meant: > > 1. The internal (or run-time) representation of null pointers, > which may be different for different pointer types. The actual > values should be of concern only to compiler writers. Authors > of C programs never see them, since they use... > > 2. The source code syntax for null pointers, which is the single > character '0'. It is often hidden behind... > > 3. The NULL macro, which is #defined to be "0" or "(void *)0". > > This article always uses the phrase "null pointer" for sense 1, the > character '0' for sense 2, and the capitalized word "NULL" for > sense 3. 295c340,342 < so because the value might change, or on some weird machine. --- > because the value might change later, or on some weird machine. > Furthermore, the distinction between the three uses of the term > "null" (listed above) is often overlooked. 308a356,370 > 13. I'm still confused. I just can't understand all this null pointer > stuff. > > A: Follow these two simple rules: > > 1. When you want to refer to a null pointer in source code, use > "0" or "NULL". > > 2. If the usage of "0" or "NULL" is in a function call, cast it to > the pointer type expected by the function being called. > > Everything else has to do with other people's confusion, or with the > internal representation of null pointers, which you shouldn't need > to know. 402c464,465 < National Standard, X3.159-1989, in the spring of 1990. For the most --- > National Standard, X3.159-1989, on December 14, 1989, and published > in the spring of 1990. For the most part, ANSI C standardizes 428a491,520 > 20. Does anyone have a tool for converting old-style C programs to ANSI > C, or for automatically generating prototypes? > > A: There are several such programs, many in the public domain. Check > your nearest comp.sources archive. (See also question 51.) > > 21. My ANSI compiler complains about a mismatch when it sees > > extern int blort(float); > int blort(x) > float x; > {... > > A: You have mixed the new-style declaration "extern int blort(float);" > with the old-style definition "int blort(x) float x;". Old C > silently promoted doubles to floats when passing them as arguments, > and made a corresponding silent change to formal argument > declarations, so the old-style definition actually says that blort > takes a double. > > The problem can be fixed either by using new-style syntax > consistently in the definition: > > int blort(float x) { ... } > > or by changing the new-style declaration to match the old-style > definition: > > extern int blort(double); 448a540,549 > 23. I'm getting strange syntax errors inside code which I've #ifdeffed > out. > > A: Under ANSI C, the text inside a "turned off" #if, #ifdef, or #ifndef > must still consist of "valid preprocessing tokens." This means that > there must be no unterminated comments or quotes (note particularly > that an apostrophe within a contracted word looks like the beginning > of a character constant) and no newlines inside quotes. 484,485c585 < vstrcat(first, ...) < char *first; --- > vstrcat(char *first, ...) 547,548c647 < error(fmt, ...) < char *fmt; --- > error(char *fmt, ...) 569a669,672 > change the va_start line to > > va_start(argp); 727a831,855 > 34. 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. If you don't have it, a suggested implementation is > > #define offset(type, mem) ((size_t)(char *)&(((type *)0)->mem)) > > This implementation's use of the null pointer, however, is said not > to be completely portable. > > See the next question for a usage hint. > > 35. 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 > > offsetof(struct a, b) > > If structp is a pointer to an instance of this structure, and b is > an int field with offset as computed above, b's value can be set > indirectly with > > *(int *)((char *)structp + offset) = value; 757a886,889 > Alternatively, define the typedefs first (using the line just above) > and follow it with the full definition of struct node, which can > then use the NODEPTR typedef for the "next" field. 795,796c927,928 < Occasionally it is necessary to precede this couplet with the < tentative declaration --- > Occasionally it is necessary to precede this couplet with the empty > declaration 802a935,938 > Again, the typedefs could also be defined before, and then used > within, the definitions for struct a and struct b. The problem > arises when an attempt is made to define and use a typedef within > the same declaration. 823c960 < cdecl> define p as pointer to function returning pointer to double --- > cdecl> declare p as pointer to function returning pointer to double 851c988 < char will probably save space.) --- > char will probably save data space.) 883,884c1020,1024 < is guaranteed to work (if TRUE is 1), but this code is obviously < silly. --- > will succeed (if a, in fact, equals b and TRUE is one), but this > code is obviously silly. In general, explicit tests against TRUE > and FALSE are undesirable, because some library functions (notably > isupper, isalpha, etc.) return, on success, a nonzero value which is > _not_ necessarily 1. 888,889c1028,1029 < ever change. That "true" is 1 and "false" (and null) 0 is < guaranteed by the language. --- > ever change. That "true" is 1 and "false" (and source-code null > pointers) 0 is guaranteed by the language. 897,905c1037,1041 < A: At the present time, there is essentially no difference. Although < many people might have wished otherwise, the ANSI standard says that < enums may be freely intermixed with integral types, without < warnings. (If such intermixing were disallowed without explicit < casts, judicious use of enums could catch certain programming < errors.) For now, the only advantage of an enum (other than that < the numeric values are automatically assigned) is that a debugger < may be able to display the symbolic value when enum variables are < examined. --- > A: At the present time, there is little difference. Although many > people might have wished otherwise, the ANSI standard says that > enums may be freely intermixed with integral types, without errors. > (If such intermixing were disallowed without explicit casts, > judicious use of enums could catch certain programming errors.) 906a1043,1050 > For now, the advantages of enums (other than that the numeric values > are automatically assigned) are that a compiler may generate > nonfatal warnings when enums and ints are indiscriminately mixed > (such mixing can still be considered bad style even though it is not > strictly illegal) or when enum cases are left out of switch > statements; and that a debugger may be able to display the symbolic > values when enum variables are examined. 919c1063 < the CBREAK or RAW bits. Under MS-DOS, use getch(). Under other --- > the terminal driver modes. Under MS-DOS, use getch(). Under other > 45. How can my program discover the complete pathname to the executable > file from which it was invoked? > > A: Depending on the operating system, argv[0] may contain all or part > of the pathname. (It may also contain nothing.) You may be able to > duplicate the command language interpreter's search path logic to > locate the executable if the name in argv[0] is incomplete. > However, there is no guaranteed or portable solution. > > 46. How can a process change an environment variable in its caller? > > A: In general, it cannot. If the calling process is prepared to listen > explicitly for some indication that its environment should be > changed, a special-case scheme can be set up. 945c1104,1105 < is, after a library function has returned an error code). --- > is, after a library function that sets errno on error has returned > an error code). 947a1107,1117 > 48. My program's prompts and intermediate output don't always show up on > my screen, especially when I pipe the output through another > program. > > A: It is best to use an explicit fflush(stdout) at any point within > your program at which output should definitely be visible. Several > mechanisms attempt to perform the fflush for you, at the "right > time," but they do not always work, particularly when stdout is a > pipe rather than a terminal. 964a1133,1134 > 50. I seem to be missing the system header file <sgtty.h>. Can someone > send me a copy? > > A: Standard headers exist in part so that definitions appropriate to > your compiler, operating system, and processer can be supplied. You > cannot just pick up a copy of someone else's header file and expect > it to work, unless that person uses exactly the same environment. > Ask your vendor why the file was not provided (or to send another > copy, if you've merely lost it). 970a1151,1153 > ptoc another comp.sources.unix contribution, this one written in > Pascal. > 974a1158,1160 > The comp.sources.unix archives also contain converters between > "K&R" C and ANSI C. 978a1164,1175 > 52. Why don't C comments nest? Are they legal inside quoted strings? > > A: C comments do not nest. For this reason, it is usually better to > "comment out" large sections of code, which might contain comments, > with #ifdef. > > The character sequences /* and */ are not special within double- > quoted strings, and do not therefore introduce comments, because a > program (particularly one which is generating C code as output) > might want to print them. 1011,1012c1207,1209 < attention to. Please send answers you might have to scs@adam.mit.edu, < for inclusions in future updates to this list. --- > attention to. Please send answers you might have to scs@adam.mit.edu > and/or scs%adam.mit.edu@mit.edu, for inclusion in future updates to this > list. 1015a1213,1215 > (Preliminary answers are net.sources/ansi.c.grammar.Z on > uunet.uu.net, FSF's GNU C compiler grammar, and the appendix to > K&R II.) 1023a1217,1218 > 57. Where can I get the "Indian Hills Style Guide" and other coding > standards? > > (I know that several of these are available at utzoo, but I don't > have the details.) > > > Other questions to be added, once I write up the answers (suggestions > for more are welcome): > > 58. How can I get these public-domain programs? > > (The answer is mostly to see the periodic postings in the > comp.sources groups.) > > 59. How can I find the day of the week given the date? > > 60. What is alloca and why is its use discouraged? > > > Thanks to Mark Brader, Joe Buehler, Christopher Calabrese, Stephen M. > Dunn, Tony Hansen, Blair Houghton, Kirk Johnson, Andrew Koenig, John > Lauro, Christopher Lott, Rich Salz, and Joshua Simons, who have > contributed, directly or indirectly, to this article. 1030a1249,1250 > The C code in this article (vstrcat, error, etc.) is public domain and > may be used without restriction.