Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: utzoo!mnetor!uunet!seismo!rutgers!ames!lll-tis!ptsfa!ihnp4!cbosgd!mandrill!hal!ncoast!allbery From: allbery@ncoast.UUCP (Brandon Allbery) Newsgroups: news.admin,comp.sources.d,comp.lang.c Subject: Re: How (not) to Program in C (was Re: PD C as solution to binary groups) Message-ID: <4261@ncoast.UUCP> Date: Tue, 25-Aug-87 21:24:35 EDT Article-I.D.: ncoast.4261 Posted: Tue Aug 25 21:24:35 1987 Date-Received: Fri, 28-Aug-87 01:39:54 EDT References: <6960@g.ms.uky.edu> <3725@ncoast.UUCP> <2527@whuts.UUCP> <2639@hoptoad.uucp> <1101@laidbak.UUCP> <3367@zen.berkeley.edu> Reply-To: allbery@ncoast.UUCP (Brandon Allbery) Followup-To: news.admin Organization: Cleveland Public Access UN*X, Cleveland, Oh Lines: 164 Xref: mnetor news.admin:908 comp.sources.d:1178 comp.lang.c:3917 As quoted from <3367@zen.berkeley.edu> by iverson@cory.Berkeley.EDU (Tim Iverson): +--------------- | In article <1101@laidbak.UUCP> guardian@laidbak.UUCP (Harry Skelton(E)) writes: | >No externs or unions (if at all possible). | | Really! How do you expect to declare the functions in all the other | modules? Perhaps you haven't discovered that when functions don't | return ints, their return value must be declared (with extern if | in a different module or a library). Admittedly I don't often | use unions, but occasionaly I found them essential. +--------------- This guy must be straight from Turbo Pascal. Son, if you want monolithic programs, stay away from real projects; it's impossible to handle a one-file source. If it's more than one file, externs are almost ESSENTIAL. (Try passing all variables needed everywhere to every function. Somehow, a 50-argument function has no appeal. Unions -- are NEVER necessary. The only legal use of a union is to shrink a variable which can contain a number of different types of values; a struct will work just as well, at a (possibly large) space penalty. Illegal uses, such as: union { struct { char lo, hi; } u_b; short u_s; } u; u.u_s = 5; printf("high byte = %d, low byte = %d\n", u.u_b.hi, u.u_b.lo); fully deserve to be rejected; there is no guarantee that a compiler will implement this as it appears to be intended. In particular, K&R doesn't assure that the elements u.u_b.lo and u.u_b.hi will be in that particular order, and doesn't assure that padding won't be inserted before or between the elements, or that u.u_b and u.u_s will be aligned, etc. +--------------- | >straight use of variables - no pointer playing. | | No pointers? This is one of the nicest things about the | language. Without this I'd have to do twice the assembly level | programming that I do now. +--------------- Gratuitous pointer usage, however, is another matter. (E.g. using pointers where ordinary variables or unions or etc. will do.) +--------------- | >no memory playing - no mallocs, allocs, callocs or whatever - | >if it cant be handled by the compiler then don't post it. | | This one's got to take the cake for all time stupidity; without | dynamic allocation most programs that use lots of memory (editors, | graphics, database, compilers, ..., i.e. just about everything) | won't be able to run on systems without virtual memory. If you | were to choose one way to make a language unpopular, lack of | dynamic allocation would be on the top of almost every list. +--------------- Or even systems *with* virtual memory. The only way to avoid malloc() and friends is (1) code fixed-length data areas: this DOES require virtual memory, huge amounts even when only a small amount is needed; also, what happens when someone needs a larger area than you defined? Or, (2) the way the Bourne shell does it: use any hunk of memory you feel like, and sbrk() it in an interrupt handler hidden from user code if you get a segmentation violation. #1 is stupid; #2 is just plain WRONG. (Oh, sure, it works (if your processor can restart interrupted instructions); but try to debug it!) +--------------- | Perhaps 20 years from now, such a statement would have merit, | but not everyone today has lots of real or virtual memory. +--------------- Not even then. Static data areas are literally self-limiting. +--------------- | >oh...main must be on bottom - plexus, IBM xenix (orig versions) and others have | >problems with main at top. (TRUE!) | | This is sick. Are you a Pascal programmer or what? Conceptualy (and | traditionaly), main belongs at the top, or for big programs, all alone. +--------------- Or maybe Forth? Again: I disbelieve that Plexus has this problem. IF some version does, it must be in one of: (a) the Z8000 Sys3's (in which case I'd blame the architecture ;-) (b) Sys3 1.2 or earlier; LONG out of date, you get what you deserve! (c) Sys5 1.2 or earler; ditto. You are also falling into a classic trap: catering to bugs that *should* be *fixed*, not encouraged. Typedefs and main being anywhere (within reason) are part of the defined standard for C; it is therefore NOT correct for standard C programs to support features which are not part of the standard. I don't care HOW enamoured you are of SCO, if their "C compiler" isn't K&R compatible, they aren't running a standard C compiler; so they have no busi- ness trying to claim to be standard. As the author of a reasonably-large C software package (a new version of which will be posted for beta test within the next few months, I hope), I sympathize with the attempt to come up with a set of standards. However, you can't legislate the difference bewteen Seventh Edition UNIX, the Berkeley Distribution, and AT&T System V out of existence. "What cannot be cured must be endured." A better guideline for programs which are DESIGNED to be portable is: (1) Don't rely on fancy features of a particular OS. This includes the following: direct screen writes/keyboard reads (microcomputers) Have a look at the multitasking discussions in comp.sys.ibm.pc if you don't understand this one. sockets, interval timer (BSD) Sockets are nice, but not available everywhere and not always emulateable. Interval timers are sometimes nice, but not every system packs a clock with the required resolution. IPC other than pipes (includes streams) (System V) The "sockets" comment applies. Include ptys here; I can't add System V ptys as posted in comp.sources.misc to my System III kernel on ncoast. file locking (System V Release 2, BSD, Xenix) The portable way is to use a link to the file being "locked"; "mail" and "passwd" do this on just about every version of UNIX. "flexnames" (BSD, System V) You can use long variable and function names, but you should arrange for them to be unique within the first seven characters. input-pending checks (BSD, Xenix) I'm sorry, but O_NDELAY under System III/V is almost useless, since you then have to do input buffering that can be difficult to understand or to implement in a program designed for Xenix or BSD. more than 512K memory required by a program (many) Smaller machines may not have it; larger ones may not be able to allocate segment descriptors for this much. Many machines don't have virtual memory. nonstandard utilities (all) As in, utmp(3) under System V; all versions of UNIX have an /etc/utmp, but not all have getutent(). system-specific files/devices/structures /etc/utmp (System V is NOT compatible with other UNIX systems!), /dev/kmem, etc.; /dev/rct (cartridge tape on Altos), /dev/od/0s (Plexus optical disk), etc. Some things are standard, or nearly so: terminal control can be defined in one of two ways, most useful standard UNIX library functions are compatible. -- Brandon S. Allbery, moderator of comp.sources.misc {{harvard,mit-eddie}!necntc,well!hoptoad,sun!mandrill!hal}!ncoast!allbery ARPA: necntc!ncoast!allbery@harvard.harvard.edu Fido: 157/502 MCI: BALLBERY <> ** Site "cwruecmp" has changed its name to "mandrill". Please re-address ** *** all mail to ncoast to pass through "mandrill" instead of "cwruecmp". ***