[comp.lang.c] How

iverson@cory.Berkeley.EDU (Tim Iverson) (08/22/87)

In article <1101@laidbak.UUCP> guardian@laidbak.UUCP (Harry Skelton(E)) writes:
>Simple use of structures or multi-array useage.

Well, if all you can write is simple programs, this ain't a bad idea.
Some people have more complex needs than yours.  If you want simple
structures, don't program in C.

>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.

>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.

>NO TYPEDEFS - some machines will croak on this. (Hi SCO Xenix)

Typedefs are standard K&R.  If SCO doesn't support them that's your
fault for making a bad buy.

>Small moduals - better a few little programs doing something than one big one.

Good idea, but you've got it all wrong.  A module is not a little *program*.
It is a set of routines that perform a common function collected into
one object file for easy debugging.  Having 10 little programs that do
the job of one is not the way to go (almost always).

>LOTS OF COMMENTS - nuff said.

No.  How 'bout *consise* comments.  I don't care how many comments there
are as long as they're to the point.

>Smart makefiles or config programs - to find out what the user does not know (see rn)

Well, suppose I have this nifty program in C that runs on WeirdOS Mark IX,
and I want to post it.  Do you expect me to spend a week writing a makefile
that will compile on all of the systems on the net?  If so you're going
to be disapointed.

A better idea would be to suggest that makefiles be provided for the
systems the program is advertised to run on.  If you want to run it
somewhere else, then its up to you to make it go.  Stop complaining;
there's lots of real nice software floating about the net (for free)
and you're complaining because someone won't hold your hand while the
stuff compiles.

>No BSD or Sys V dependent stuff - must be able to compile 'clean' on any system.

While you're at it why don't you say no Pascal or Fortran.  Porting C
between the two really isn't that hard.  Again, this software is
free!  Don't complain if its not waranted.

>vars must have legable names - no pt.dk.i2.dv - put.disk.in2.drive <--- better

Nice sentiment, but I'd rather have small variable names in small functions
with good function names than than long names everywhere.  I'd rather see
check_for_errors(foo), than foo(this_might_have_errors).

>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.

Perhaps 20 years from now, such a statement would have merit,
but not everyone today has lots of real or virtual memory.

>use standard includes - stdio.h curses.h termcap.h ctype.h ect....

Curses.h and termcap.h are not standard (unless you're talking SysV or
BSD :-).  If the thing runs on what the poster says it will run on,
don't complain.

>include complete documents....

Good idea, but I wouldn't insist on it.

>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.

>My opinions are not those of my company!

Good.  If they were, I'd never buy anything your company sells.

I really don't see what you're complaining about.  All of the software
I've gotten off the net has done pretty much what it advertised to
do, and alot of the big packages have been very high quality.  Considering
that all this nice *source* is free, there is no way I'd try to impose
restrictions on the style of programming these people indulge in.


- Tim Iverson
  iverson@cory.Berkeley.EDU
  ucbvax!cory!iverson

allbery@ncoast.UUCP (Brandon Allbery) (08/26/87)

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
   <<ncoast Public Access UNIX: +1 216 781 6201 24hrs. 300/1200/2400 baud>>
** Site "cwruecmp" has changed its name to "mandrill".  Please re-address **
*** all mail to ncoast to pass through "mandrill" instead of "cwruecmp". ***

STROBL%DBNGMD21.BITNET@wiscvm.wis (Wolfgang Strobl 49+228303223) (08/29/87)

> 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,

You contradict yourself here - or did I miss the irony?

On page 138 of K&R they say:
  "A union is a variable which may hold (at different times)
  objects of different types and sizes, with the compiler keeping
  track of size and alignment requirements. Unions provide a way to
  manipulate different kinds of data in a single area of storage,
  without embedding any machine-dependent information in the program."
There is nothing more to say, I think.

Wolfgang Strobl, STROBL@DBNGMD21.BITNET

gwyn@brl-smoke.ARPA (Doug Gwyn ) (08/29/87)

In article <9057@brl-adm.ARPA> STROBL%DBNGMD21.BITNET@wiscvm.wis (Wolfgang Strobl 49+228303223) writes:
>There is nothing more to say, I think.

Wrong -- you could explain why you quote a passage from K&R that
backs up the statement you were taking exception to.

STROBL%DBNGMD21.BITNET@wiscvm.wis (Wolfgang Strobl 49+228303223) (08/31/87)

In a message with timestamp 29 AUG 87 07:39:56 Doug Gwyn
<gwyn@brl-smoke.arpa> writes

> In article <9057@brl-adm.ARPA> STROBL%DBNGMD21.BITNET@wiscvm.wis (Wolfgang
>  Strobl 49+228303223) writes:
> >There is nothing more to say, I think.
>
> Wrong -- you could explain why you quote a passage from K&R that
> backs up the statement you were taking exception to.

With pleasure. Please excuse errors in my language; it's difficult
to do such hairsplitting as we do here in a foreign language.

The paragraph from K&R I quoted in my reply had an explicit statement
about what unions are good for (be refered to the fragments "..
compiler keeping track of size and alignment requirements ...  without
embedding any machine-dependent information in the program ..."; I don't
want to repeat the quote). The statement I took exception to did not
mention these virtues but banned Unions because of potential abuse.

So far I do not understand what remains to be explained, but you are
right:  there is more to say, I take that back.

The original message of Brandon Allbery <allbery@ncoast.uucp> said
|
|  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,
|  ... (rest omitted)

This gives a rule: Unions are NEVER necessary and explains it with an
exception to that rule: the use of Unions   i s   necessary if you don't
have an arbitrary amount of space to your disposal (as the proposed
replacement of Unions by Structs would require).

This I called a contradiction. Now, if it makes no difference to
you whether your program needs say ten times more space, you may
replace portably used Unions by Structs.

But even then it makes no sense. Consider any program which makes
portable use of Unions (in the way described in K&R).  It contains
declarations of variables which may contain values of different types
at different times, but only one type and value at any point in time.
All C compilers I know of are not able to check whether a program acts
that way, but with a runtime check it can be done. At least the
information (that a structured variable will have only one value in one
of a its members at any one time) is in the source program. Please note
that I do not suggest a type tag for Unions which is accessable to the
programmer.

Now replace all Unions by Structs, as proposed. Please explain why this
is any better.  Will a program which stores one member and uses another
later be less erroneous then? Very seldom.

The only changes I see here are

 - programs in which the programmer erroneously assumed no overlapping
   of variable usage and used Unions now work (the store mem1, store
   mem2, use mem1 case). Such programs are probable wrong anyhow :-)

 - programs where the program erroneously accesses a variable via the
   wrong member because of a programming error now behave differently:
   Union: store mem1, use mem2 gave the machine dependent bit
          pattern of the mem1 value interpreted as mem2 value.
          This normally creates machine dependent garbage.
   Struct: the above sequence gives the last value stored via mem2,
          if any. The result may be garbage, zero or an usable, but
          nevertheless wrong value.

 - after the change one cannot say from the program text alone whether
   some usage patterns for a variable are right or wrong. Some static
   and dynamic checking possibilities are lost.

Conclusion:

I find Unions usefull as a construct which allows me to express usage
restrictions to a structured variable in a formal way, checkable by the
compiler and me, with the added bonus of big space savings.

Wolfgang Strobl, GMD Z1.BN, STROBL@DBNGMD21.BITNET