mautner@odin.ucsd.edu (Craig Mautner) (09/25/90)
My apologies for the consumption of bandwidth but I wanted to send this through properly. The last time it had the wrong Subject line. The author of this does not have access to the news groups. He asked me to post this and see what comments it generates. Any correspondence should be sent to him at the internet address included in the header. -Craig Mautner //////////////////// Begin Included Message //////////////////////// Seven Original Sins of K&R by Philip J. Erdelsky Compuserve: 75746,3411 Internet: 75746.3411@compuserve.com September 22, 1990 The creation of C approximately two decades ago was a wondrous event, even if it did not seem so at the time. Like all human creations, C was imperfect. I have identified seven Original Sins--minor flaws in C for which K&R will eventually have to answer, in this world or the next. I call them original sins because they were present when C originated, not because K&R were the first to commit them. Some of these sins have been purged from later versions of C, but others remain with us. I am not the first to decry these sins, nor will I be the last. I am merely another in a long series of prophets crying in the wilderness. I The First Original Sin was pitifully weak typing. There is no Boolean type in C, so generations of programmers have erroneously written something like "if (x=5)" instead of "if (x==5)", only to wonder why x always seems to be 5, regardless of what has gone before. The "char" type was not specified as either signed or unsigned. This sin has probably wasted more CPU time than any other, as savvy programmers learn to put a defensive "&0xFF" after every "char" expression that needs to be unsigned. The default type for functions should have been "void", not "int", but there was originally no "void" type. Modern compilers have provided partial redemption from this sin, usually by issuing warning messages when the program appears to be tainted. But these warnings are often false alarms and go unheeded. There is still no Boolean type, and "char" may be either signed or unsigned. Even the new enumeration types are merely integers in disguise, just as willing to be mixed as matched. II The Second Original Sin was the failure to make "NULL" a keyword. Beginning C programmers wonder why you have to "#include <stdio.h>" in a program that doesn't use standard I/O. Some compilers don't even object when you assign an integer constant to a pointer without a typecast, especially when the constant happens to be zero. Don't blame the compiler. The poor thing can't tell the difference between a zero integer constant and "NULL". Redemption from this sin is on its way. Modern compilers define "NULL" as "(void *) 0", so there's at least some hope of distinguishing it from a plain old zero. III The Third Original Sin was the use of the keyword "static" to mark a function or variable as local to particular source file. This is really a trinity of sins. The word "static" doesn't mean local. It conflicts with the other use of the word "static"--to mark a variable inside a function as one that actually is static, in an accepted meaning of the word. Finally, even if the word "local" had been used instead, it would have been marking the wrong thing. The word "public", or some similar word, should have been used to mark the few functions and variables that must be made available to the code in other files. Other functions and variables should have been local by default. That's how it's done in assembly language and other high-level languages, and the reason for it is obvious. From this sin, however, no redemption is in sight. IV The Fourth Original Sin is the mandatory use of the "break" keyword to terminate a "case" clause in a "switch" statement. Omitting it is natural for beginning programmers, and sometimes even for experienced programmers who have been dabbling in more tightly structured languages. Of course, this causes control to fall through to the next case, which is occasionally useful but nearly always a mistake, like a double exposure in photography. But the evil goes even further. Often, the "switch" statement is enclosed in a "for" or "while" loop. You want to finish up a "case" clause by breaking out of the loop? You can't do it in C, not without breaking out of the "switch" statement first! The solution, not likely to be adopted even in C+++, would be to have the compiler put an implicit "break" at the end of every "case" clause, and reserve the "break" keyword for breaking out of loops, the way God intended. V The Fifth Original Sin was the way functions are defined. The entire parameter list has to be written twice. That's something no programmer should have to do unless it's absolutely necessary. And to compound the evil, an untyped parameter defaults to type "int". Most programmers have written something like "strcmp(s,t)", forgetting the declaration "char *s,*t;". What you wind up with in most cases is, not a function that fails, but something worse--a function that works as long as pointers and integers are the same size, and then fails when you try to port it. Fortunately, ANSI C permits prototype definitions, but the old way is still permitted, at least during a transitional period. Let's hope the transition is brief. VI The Sixth Original Sin was the way conflicts among the names of members of different structures were neither forbidden nor resolved. The original K&R said that different structures could have members with identical names as long as they had identical offsets. The way early compilers implemented this dictum varied. Some compilers would check to see that the offsets were indeed identical. Others simply generated erroneous code when they weren't. Most programmers took the safest course by including the structure name--usually abbreviated--in every member name. Modern compilers have atoned for this sin completely by keeping a separate member list for each structure type. This resolves the conflicts, but a reminder of past iniquities persists in the awkward names of structure members in UNIX source code and other old C scriptures. VII The Seventh Original Sin was the eight-character limit on distinguishable names, or even fewer than eight for externally defined names. Of course, some such limitation was required for efficient implementation, but eight characters are not enough. C was much better than Fortran, which allowed only six, but there are many pairs of English words with distinct meanings whose first eight letters are identical. The minimum number depends on the language, but for English about 20 should be sufficient. German programmers need more. Most modern compilers do have a reasonable limit, but some compiler developers have apparently forgotten that virtue lies in moderation. One compiler allows at least several hundred characters, maybe more. That's too long. Compilers are supposed to compile, not test the limits of computability by allowing single labels to occupy practically the entire computer memory (and disk swap area). An unprintable name--one that won't fit on a single line--should also be uncompilable. Epilogue None of these sins is inconsistent with the philosophy of C. We needn't embrace heresies like Pascal, Modula 2 or Ada. But we must abandon the false god of 100% upward compatibility. We must tear down the old temple to build a new one. Then, and only then, will our redemption be at hand. Note This jeremiad is not copyrighted. You are welcome to copy it and pass it on. I only ask you to leave my name and account number on it. Let me take the credit--and the heat. //////////////////// End Included Message //////////////////////// -- -------------------------------------------------------------------- Craig D. Mautner UCSD mautner@cs.ucsd.edu Dept of CSE, C-014 (619) 534-4526 La Jolla, Ca. 92093
vd09+@andrew.cmu.edu (Vincent M. Del Vecchio) (09/26/90)
> Excerpts from netnews.comp.lang.c: 25-Sep-90 Seven Original Sins of K&R > .. Craig Mautner@odin.ucsd. (8365) > None of these sins is inconsistent with the philosophy > of C. We needn't embrace heresies like Pascal, Modula > 2 or Ada. But we must abandon the false god of 100% > upward compatibility. We must tear down the old temple > to build a new one. Then, and only then, will our > redemption be at hand. I don't know about this. There are (unfortunately) still so many pre-ANSI compilers and so much pre-ANSI code (not to mention code that depends on the existence of the other "sins" that you mentioned) in use that it would be ridiculous for the time being to abandon backward compatibility. I like in general the style of the gcc, accepting both older and newer code with command-line switches to specify explicitly one or the other. But pre-ANSI code will be around for a good while to come. +----------------------------------------------------------------------------+ | Vincent Del Vecchio \ Disclaimer: Views expressed are not necessarily | | Box 4834 \ those of any person/group I am associated with. | | 5125 Margaret Morrison St.\ UUCP: {uunet,harvard}!andrew.cmu.edu!vd09 | | Pittsburgh, PA 15213 \ BITNET: vd09+%andrew@cmuccvma.bitnet | | (412) 268-4441 \ Internet: vd09+@andrew.cmu.edu | +----------------------------------------------------------------------------+
gillies@m.cs.uiuc.edu (09/26/90)
Re: Sin #IV Hey, how else can I write the following amazingly convoluted code (idea courtest of Harbison & Steele's book, first edition): main() { int x,i; x=1; switch(x) { case 1: for (i=0; i < 10; i++) case 2: printf("%d ",i); } } And the result: 0 1 2 3 4 5 6 7 8 9
tom@ssd.csd.harris.com (Tom Horsley) (09/26/90)
What? only seven?
In this list, the only one that seems unforgivable to me is VII - short
names, but you left out the most absolutely awful and despicable sin of all:
VIII
The eight (and worst) original sin was allowing arrays to (sometimes) be
kind of automatically converted sort-of into pointers to the first element
of the array except when they aren't. Without a doubt this psuedo
equivalence between arrays and pointers that works most of the time except
when it doesn't has caused more confusion and twisted more brains of people
trying to learn C than any other feature. If I want the address of an
array, why not stick an '&' operator in front of it like I have to do for
EVERY OTHER kind of variable in C?
--
======================================================================
domain: tahorsley@csd.harris.com USMail: Tom Horsley
uucp: ...!uunet!hcx1!tahorsley 511 Kingbird Circle
Delray Beach, FL 33444
+==== Censorship is the only form of Obscenity ======================+
| (Wait, I forgot government tobacco subsidies...) |
+====================================================================+
rv@erix.ericsson.se (Robert Virding) (09/26/90)
In article <12780@sdcc6.ucsd.edu>, mautner@odin.ucsd.edu (Craig Mautner) writes: > Seven Original Sins of K&R > by Philip J. Erdelsky > > I > {Weak typing, reaaly no bools and char neither signed or unsigned} > The "char" type was not specified as either >signed or unsigned. This sin has probably wasted more >CPU time than any other, as savvy programmers learn to >put a defensive "&0xFF" after every "char" expression >that needs to be unsigned. This is no REAL problem, if you are going to do operations which should be unsigned, just declare the variables as 'unsigned char'. A (really) savvy programmer would *NEVER* put a &0xff after every char expression. A novice would. > II > Some compilers don't even object when >you assign an integer constant to a pointer without a >typecast, especially when the constant happens to be >zero. Don't blame the compiler. The poor thing can't >tell the difference between a zero integer constant and >"NULL". According to the language definition assigning a zero to a pointer is perfectly legal, the compiler shouldn't complain. All C compilers I have seen will complain for any other integer. For the 50 million'th time in this group, there is no difference between zero and NULL. > III > {static} Granted. > IV > {break} What's the problem? "break" means break out of the surrounding while/for/case. The REAL sin is that "break" ignores a surrounding if. This really can cause problems. >The solution, not likely to be adopted even in C+++, >would be to have the compiler put an implicit "break" >at the end of every "case" clause, and reserve the >"break" keyword for breaking out of loops, the way God >intended. I hope it is NEVER adopted! Being able to "fall through" is extremely pratical and saves much code copying or "goto"s. Adding the "break" is really no problem. > V > {defining function arguments} >Most programmers have written something like >"strcmp(s,t)", forgetting the declaration "char >*s,*t;". What you wind up with in most cases is, not a >function that fails, but something worse--a function >that works as long as pointers and integers are the >same size, and then fails when you try to port it. Actually all compilers will complain when you try to USE "s" and "t" as pointers > VI > {struct member name conflicts} True, but extremely practical. Saved typing, no need to define a union of possible structures and adding union element names to every reference :-). > VII >{eight character name limit} Agreed, but unfortunately C had/has to exist on systems which themselves limit the name length (in linkers and such). We could I suppose always say "don't run C on such systems". > Epilogue > >None of these sins is inconsistent with the philosophy >of C. If the sins are consistent with the philosophy of C would there correction then be inconsistent? :-)
mcdonald@aries.scs.uiuc.edu (Doug McDonald) (09/26/90)
In article <4700066@m.cs.uiuc.edu> gillies@m.cs.uiuc.edu writes: > >Re: Sin #IV > >Hey, how else can I write the following amazingly convoluted code >(idea courtest of Harbison & Steele's book, first edition): > >main() >{ >int x,i; >x=1; >switch(x) { > case 1: > for (i=0; i < 10; i++) > case 2: > printf("%d ",i); >} >} > >And the result: > >0 1 2 3 4 5 6 7 8 9 Well, in a C-like language WHERE THE CASES DIDN'T FALL THROUGH you could write: >main() >{ >int x,i; >x=1; >switch(x) { > case 1: > for (i=0; i < 10; i++) goto 2; > case 2: > printf("%d ",i); >} >} Doug McDonald
goudreau@dg-rtp.dg.com (Bob Goudreau) (09/26/90)
In article <12780@sdcc6.ucsd.edu>, mautner@odin.ucsd.edu (Craig Mautner) writes: > > The Second Original Sin was the failure to make "NULL" > a keyword. Beginning C programmers wonder why you have > to "#include <stdio.h>" in a program that doesn't use > standard I/O. Some compilers don't even object when > you assign an integer constant to a pointer without a > typecast, especially when the constant happens to be > zero. Don't blame the compiler. The poor thing can't > tell the difference between a zero integer constant and > "NULL". Or better yet, how about a new operator named "nil", which takes a type name (sorry, pointer types only need apply) and which evaluates to the nil pointer of that type? For example, char * cp; .... if (cp == nil(char *)) .... Of course, it's easy enough to implement now as a macro, but think of all the comp.lang.c articles that could have been avoided by building it into the language and thus avoiding having the token "0" do double duty... ---------------------------------------------------------------------- Bob Goudreau +1 919 248 6231 Data General Corporation 62 Alexander Drive goudreau@dg-rtp.dg.com Research Triangle Park, NC 27709 ...!mcnc!rti!xyzzy!goudreau USA
roy@phri.nyu.edu (Roy Smith) (09/27/90)
goudreau@dg-rtp.dg.com (Bob Goudreau) writes: >> The Second Original Sin was the failure to make "NULL" a keyword. What about this for a portable way to define NULL: #define NULL (""[1]) would that work? -- Roy Smith, Public Health Research Institute 455 First Avenue, New York, NY 10016 roy@alanine.phri.nyu.edu -OR- {att,cmcl2,rutgers,hombre}!phri!roy "Arcane? Did you say arcane? It wouldn't be Unix if it wasn't arcane!"
jh4o+@andrew.cmu.edu (Jeffrey T. Hutzelman) (09/27/90)
rv@erix.ericsson.se (Robert Virding) writes: >In article <12780@sdcc6.ucsd.edu>, mautner@odin.ucsd.edu (Craig >Mautner) writes: >> Seven Original Sins of K&R >> by Philip J. Erdelsky > >> II >> Some compilers don't even object when >>you assign an integer constant to a pointer without a >>typecast, especially when the constant happens to be >>zero. Don't blame the compiler. The poor thing can't >>tell the difference between a zero integer constant and >>"NULL". > >According to the language definition assigning a zero to a pointer is >perfectly legal, the compiler shouldn't complain. All C compilers I >have seen will complain for any other integer. For the 50 million'th >time in this group, there is no difference between zero and NULL. I know of one compiler (on a 16-bit micro) that will not complain if you use any other integer or long int. Pointers on that machine are (exaclty) same as unsigned long ints, and the compiler lets you say void function(void) { unsigned char *pointer; unsigned long int integer; integer=0xE0C000; for(pointer=integer;!(*pointer && 0x80);); /* wait for keypress */ printf("%#04x",*pointer & 0x7F); /* strip off flag bit */ integer=0xE0C010; *pointer=0; /* reset keyboard latch and/or advance buffer */ } which will wait for a keypress and print out its ASCII value (on an Apple IIgs, under ORCA/C 1.0 or 1.1). ----------------- Jeffrey Hutzelman America Online: JeffreyH11 Internet/BITNET:jh4o+@andrew.cmu.edu, jhutz@drycas.club.cc.cmu.edu >> Apple // Forever!!! <<
goudreau@dg-rtp.dg.com (Bob Goudreau) (09/27/90)
In article <1990Sep26.193626.721@phri.nyu.edu>, roy@phri.nyu.edu (Roy Smith) writes: > goudreau@dg-rtp.dg.com (Bob Goudreau) writes: > >> The Second Original Sin was the failure to make "NULL" a keyword. Please keep your attributions straight; I did not write that sentence. > What about this for a portable way to define NULL: > > #define NULL (""[1]) > > would that work? Nope; it's not even *defined* behavior to access beyond the end of an array, which is what you've done. ---------------------------------------------------------------------- Bob Goudreau +1 919 248 6231 Data General Corporation 62 Alexander Drive goudreau@dg-rtp.dg.com Research Triangle Park, NC 27709 ...!mcnc!rti!xyzzy!goudreau USA
maunz@warwick.ac.uk (The Teenage Student WINJA Turbot) (09/27/90)
In article <1990Sep26.193626.721@phri.nyu.edu> roy@phri.nyu.edu (Roy Smith) writes: > >What about this for a portable way to define NULL: > >#define NULL (""[1]) > >would that work? B L E U G H ! ! This is a joke, right? ("") is a null-terminated empty string, no? Functionally equivalent to a char pointer which refers to an ASCII NUL or char (0), no? (""[1]) is probably a char pointer to garbage, no? Either this is a joke, or I have missed the point. Either way I'm stupid. I must agree with the poster/author of the 'original sins' about NULL though. It would be nice if NULL had been made unnecessary by a standardised keyword such as 'nullpointer' or something. But nobody could have expected K & R to have crystal balls. /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\ \ \/ /. \ JANET maunz@uk.ac.warwick.cu / "As the people here grow \/\/ I N J A \ (K R Turner) / colder..." -- Kate Bush \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
maunz@warwick.ac.uk (The Teenage Student WINJA Turbot) (09/27/90)
In article <1990Sep27.073730.26575@warwick.ac.uk> maunz@warwick.ac.uk (The Teenage Student WINJA Turbot) writes: >In article <1990Sep26.193626.721@phri.nyu.edu> roy@phri.nyu.edu (Roy Smith) writes: >> >>What about this for a portable way to define NULL: >> >>#define NULL (""[1]) >> >>would that work? > > B L E U G H ! ! > >This is a joke, right? >("") is a null-terminated empty string, no? >Functionally equivalent to a char pointer which refers to an ASCII NUL or >char (0), no? >(""[1]) is probably a char pointer to garbage, no? Well that proves I'm stupid. I meant (""[1]) is probably a garbage char, honest, your honour! >Either this is a joke, or I have missed the point. >Either way I'm stupid. >I must agree with the poster/author of the 'original sins' about NULL though. >It would be nice if NULL had been made unnecessary by a standardised keyword >such as 'nullpointer' or something. But nobody could have expected K & R to >have crystal balls. /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\ \ \/ /. \ JANET maunz@uk.ac.warwick.cu / "As the people here grow \/\/ I N J A \ (K R Turner) / colder..." -- Kate Bush \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
roy@phri.nyu.edu (Roy Smith) (09/27/90)
I wrote: > #define NULL (""[1]) maunz@warwick.ac.uk (The Teenage Student WINJA Turbot) responded: > B L E U G H ! ! You have such a way with words :-). It is clear from the various bits of mail I've gotten, and postings such as this, that folks on this group don't think too highly of my idea. Part of the problem is that I made a braino (similar to a typo, but occuring above the neck); I meant to write: #define NULL (""[0]) It's also clear that people probably won't think too highly of that either, so I guess we can just drop it. -- Roy Smith, Public Health Research Institute 455 First Avenue, New York, NY 10016 roy@alanine.phri.nyu.edu -OR- {att,cmcl2,rutgers,hombre}!phri!roy "Arcane? Did you say arcane? It wouldn't be Unix if it wasn't arcane!"
henry@zoo.toronto.edu (Henry Spencer) (09/27/90)
In article <1990Sep26.193626.721@phri.nyu.edu> roy@phri.nyu.edu (Roy Smith) writes: >What about this for a portable way to define NULL: > >#define NULL (""[1]) > >would that work? Uh, to do what? NULL is a null *pointer*, not a '\0' character. (That should be [0], and in any case this will not work in initializers because it is not a compile-time expression under the official rules.) -- TCP/IP: handling tomorrow's loads today| Henry Spencer at U of Toronto Zoology OSI: handling yesterday's loads someday| henry@zoo.toronto.edu utzoo!henry
merriman@ccavax.camb.com (09/28/90)
In article <1990Sep26.193626.721@phri.nyu.edu>, roy@phri.nyu.edu (Roy Smith) writes: > goudreau@dg-rtp.dg.com (Bob Goudreau) writes: >>> The Second Original Sin was the failure to make "NULL" a keyword. > > What about this for a portable way to define NULL: > > #define NULL (""[1]) > > would that work? > -- > Roy Smith, Public Health Research Institute > 455 First Avenue, New York, NY 10016 > roy@alanine.phri.nyu.edu -OR- {att,cmcl2,rutgers,hombre}!phri!roy > "Arcane? Did you say arcane? It wouldn't be Unix if it wasn't arcane!" NULL is a pointer type! NUL is an ASCII character!
jeenglis@alcor.usc.edu (Joe English Muffin) (09/28/90)
tom@ssd.csd.harris.com (Tom Horsley) writes: >The eight (and worst) original sin was allowing arrays to (sometimes) be >kind of automatically converted sort-of into pointers to the first element >of the array except when they aren't. C's array semantics make perfect sense once you understand C's *pointer* semantics, which are probably the most unique (and elegant, IMHO) feature of the language. The only wart I can see on the language wrt. arrays is that int foo(bar) char bar[]; { ... } is legal syntax. >Without a doubt this psuedo >equivalence between arrays and pointers that works most of the time except >when it doesn't has caused more confusion and twisted more brains of people >trying to learn C than any other feature. Actually, it's probably _strings_ that have boggled beginners with backgrounds in BASIC, causing confusion and core dumps, dismaying dozens of dumbfounded dopes, than anything else. How many times have *you* seen a C neophyte go nuts trying to figure out why 'string1 = strcat(string2,string3);' doesn't work as expected? Of course, strings make perfect sense too once you understand pointers. I hardly consider these things an 'original sin.' They're natural extensions of a fundamental part of the language, which is really quite simple to understand. --jeenglis@alcor.usc.edu
ok@goanna.cs.rmit.oz.au (Richard A. O'Keefe) (09/28/90)
In article <4700066@m.cs.uiuc.edu>, gillies@m.cs.uiuc.edu writes: > Hey, how else can I write the following amazingly convoluted code > (idea courtest of Harbison & Steele's book, first edition): > main() > { > int x,i; > x=1; > switch(x) { > case 1: > for (i=0; i < 10; i++) > case 2: > printf("%d ",i); > } > } Easily: main() { int i; for (i = 0; i < 10; i++) printf("%d ", i); exit(0); /* you shouldn't leave this out */ } This was possible because of the assignment x=1. If that assignment had been x=2, the effect would have been undefined because i was not initialised. That's a good reason not to jump into loops even if C lets you. -- Fixed in the next release.
s64421@zeus.usq.edu.au (house ron) (09/28/90)
goudreau@dg-rtp.dg.com (Bob Goudreau) writes: >In article <1990Sep26.193626.721@phri.nyu.edu>, roy@phri.nyu.edu (Roy >Smith) writes: >> >> #define NULL (""[1]) >> >> would that work? >Nope; it's not even *defined* behavior to access beyond the end of >an array, which is what you've done. I think he means #define NULL (""[0]) -- Regards, Ron House. (s64421@zeus.usq.edu.au) (By post: Info Tech, U.C.S.Q. Toowoomba. Australia. 4350)
henry@zoo.toronto.edu (Henry Spencer) (09/28/90)
In article <1990Sep27.131329.26616@phri.nyu.edu> roy@phri.nyu.edu (Roy Smith) writes: >... I meant to >write: > >#define NULL (""[0]) Roy, apart from not being a compile-time value, which limits its use, this is exactly and precisely equivalent to #define NULL 0 Might one ask what you are trying to accomplish with it? -- Imagine life with OS/360 the standard | Henry Spencer at U of Toronto Zoology operating system. Now think about X. | henry@zoo.toronto.edu utzoo!henry
rhealey@digibd.com (Rob Healey) (09/28/90)
In article <12777@sdcc6.ucsd.edu> 75746.3411@compuserve.com writes: >The author of this does not have access to the news groups. >He asked me to post this and see what comments it generates. >Any correspondence should be sent to him at the internet address >included in the header. > > Seven Original Sins of K&R > by Philip J. Erdelsky > Compuserve: 75746,3411 > Internet: 75746.3411@compuserve.com > September 22, 1990 > Just general comment on the whole document: C wasn't designed to be a general purpose language, it was designed to help in the porting of an OS. C is a language that is more useful for OS work than for intro to programming 101. C is also not for people who have traditionally had their hands held by a compiler, i.e. strong typing and a plethora of data types. C is best used in situations where you need to avoid strong typing rather than encourage it. Most of the complaints in this article would be best solved if the author used the correct language for the task, one with strong typing and features that held your hands along the way so you didn't have to think as hard or be as careful. C isn't the only language in the world, use the language that best fits your need. These people who want A language to be all things to all applications are attacking the problem from the wrong angle. If I want quick, simple and dirty BASIC does a good job. If I want to do a device driver and feel too lazy to use assembly I'll use C. If I want to do database work I'll use SQL or a 4GL. If I want to do expert systems I'll use LISP, scheme or an OOL. As the man said: "The right tool for the right job" Rather than turning C into the Ada from HELL, use a better language for your needs. 'Nuff said, -Rob Speaking for self, not company.
roy@phri.nyu.edu (Roy Smith) (09/29/90)
henry@zoo.toronto.edu (Henry Spencer) writes: > Roy, apart from not being a compile-time value, which limits its use, > this is exactly and precisely equivalent to > #define NULL 0 > Might one ask what you are trying to accomplish with it? One might, but it probably wouldn't do much good at this point. As somebody pointed out to me in email, the first rule of holes is that when you're in one, you should stop digging. Suffice it to say it was a half-baked idea and I wish I hadn't brought it up in the first place. -- Roy Smith, Public Health Research Institute 455 First Avenue, New York, NY 10016 roy@alanine.phri.nyu.edu -OR- {att,cmcl2,rutgers,hombre}!phri!roy "Arcane? Did you say arcane? It wouldn't be Unix if it wasn't arcane!"
goudreau@dg-rtp.dg.com (Bob Goudreau) (09/29/90)
In article <1990Sep28.112637.10446@zeus.usq.edu.au>, s64421@zeus.usq.edu.au (house ron) writes: > goudreau@dg-rtp.dg.com (Bob Goudreau) writes: > > >In article <1990Sep26.193626.721@phri.nyu.edu>, roy@phri.nyu.edu (Roy > >Smith) writes: > >> > >> #define NULL (""[1]) > >> > >> would that work? > > >Nope; it's not even *defined* behavior to access beyond the end of > >an array, which is what you've done. > > I think he means > > #define NULL (""[0]) ... which is still wrong, though at least it's a legal array access. The NUL character ('\0') is *not* the same as the null pointer. See the FAQ posting for details. ---------------------------------------------------------------------- Bob Goudreau +1 919 248 6231 Data General Corporation 62 Alexander Drive goudreau@dg-rtp.dg.com Research Triangle Park, NC 27709 ...!mcnc!rti!xyzzy!goudreau USA
userAKDU@mts.ucs.UAlberta.CA (Al Dunbar) (09/29/90)
In article <1990Sep28.112637.10446@zeus.usq.edu.au>, s64421@zeus.usq.edu.au (house ron) writes: >goudreau@dg-rtp.dg.com (Bob Goudreau) writes: > >>In article <1990Sep26.193626.721@phri.nyu.edu>, roy@phri.nyu.edu (Roy >>Smith) writes: >>> >>> #define NULL (""[1]) >>> >>> would that work? > >>Nope; it's not even *defined* behavior to access beyond the end of >>an array, which is what you've done. > >I think he means > > #define NULL (""[0]) > >-- >Regards, > >Ron House. (s64421@zeus.usq.edu.au) >(By post: Info Tech, U.C.S.Q. Toowoomba. Australia. 4350) Wait a minute here. Am I missing something? Wouldn't (""?0?) be a pointer to a null (zero length) string rather than a NULL pointer (i.e. a pointer not pointing validly)? -------------------+------------------------------------------- Al Dunbar | Edmonton, Alberta | this space for rent CANADA | -------------------+-------------------------------------------
salomon@ccu.umanitoba.ca (Dan Salomon) (10/02/90)
In article <sazwbR600Vp6IHhVVV@andrew.cmu.edu> vd09+@andrew.cmu.edu (Vincent M. Del Vecchio) writes: > I don't know about this. There are (unfortunately) still so many > pre-ANSI compilers and so much pre-ANSI code (not to mention code that > depends on the existence of the other "sins" that you mentioned) in use > that it would be ridiculous for the time being to abandon backward > compatibility. Much more code is going to be written in C than currently exists. Should we sacrifice all the code to come for the sake of the existing code? -- Dan Salomon -- salomon@ccu.UManitoba.CA
rns@se-sd.SanDiego.NCR.COM (Rick Schubert) (10/02/90)
[I know I should probably let this go since this is a dead issue, but I couldn't resist improving on Henry's answer. I hope I'm not missing something, since I'm surprised he didn't also say what I'm going to.] In <1990Sep28.144753.23727@zoo.toronto.edu> henry@zoo.toronto.edu (Henry Spencer) writes: >In article <1990Sep27.131329.26616@phri.nyu.edu> roy@phri.nyu.edu (Roy Smith) writes: >>... I meant to >>write: >> >>#define NULL (""[0]) >Roy, apart from not being a compile-time value, which limits its use, >this is exactly and precisely equivalent to >#define NULL 0 Since (""[0]) is not a compile-time value (I assume that's the same thing as a constant expression), it is also not a null-pointer constant. It DOES have the value 0, but the only arithmetic expressions that are null pointers are those that are constant expressions evaluating to 0. -- Rick Schubert (rns@se-sd.sandiego.NCR.COM)
hp@vmars.tuwien.ac.at (Peter Holzer) (10/02/90)
rv@erix.ericsson.se (Robert Virding) writes: >What's the problem? "break" means break out of the surrounding >while/for/case. The REAL sin is that "break" ignores a surrounding if. >This really can cause problems. Like in: 1: for (;;) { 2: /* code */ 3: if (expression) break; 4: /* more code */ 5: } If break would break out of the surrounding if, it would not break out of the loop, so line 3 would just be a noop. -- | _ | Peter J. Holzer | Think of it | | |_|_) | Technische Universitaet Wien | as evolution | | | | | hp@vmars.tuwien.ac.at | in action! | | __/ | ...!uunet!mcsun!tuvie!vmars!hp | Tony Rand |
seanf@sco.COM (Sean Fagan) (10/03/90)
In article <1990Sep26.134716.17540@ux1.cso.uiuc.edu> mcdonald@aries.scs.uiuc.edu (Doug McDonald) writes: >Well, in a C-like language WHERE THE CASES DIDN'T FALL THROUGH >you could write: >>switch(x) { >> case 1: >> for (i=0; i < 10; i++) > goto 2; >> case 2: >> printf("%d ",i); Which, of course, prints out 0 *only*, which is not what the original did at all (although, I will admit, the original wasn't very clever, interesting, novel, obfuscated, but it was rather stupid). -- -----------------+ Sean Eric Fagan | "Never knock on Death's door: ring the bell and seanf@sco.COM | run away! Death really hates that!" uunet!sco!seanf | -- Dr. Mike Stratford (Matt Frewer, "Doctor, Doctor") (408) 458-1422 | Any opinions expressed are my own, not my employers'.
dts@quad.sialis.mn.org (David T. Sandberg) (10/03/90)
In article <1990Oct2.040019.1635@ccu.umanitoba.ca> salomon@ccu.umanitoba.ca (Dan Salomon) writes: >Much more code is going to be written in C than currently exists. >Should we sacrifice all the code to come for the sake of the existing >code? Apples and oranges. Maintaining backward compatibility doesn't "sacrifice" all future code... it just means that you can't have every toy construct you may want. That in and of itself doesn't prevent you from using the language, and is not nearly so serious as the problems that would be caused by breaking most every bit of existing code (a real, quantifiable sacrifice). -- \\ David Sandberg \ ,=, ,=, \\ // dts@quad.sialis.mn.org / | |uadric '=,ystems // \\ uunet!rosevax!sialis!quad!dts \ '=\ `=' \\
henry@zoo.toronto.edu (Henry Spencer) (10/04/90)
In article <3945@se-sd.SanDiego.NCR.COM> rns@se-sd.SanDiego.NCR.COM (Rick Schubert) writes: >Since (""[0]) is not a compile-time value (I assume that's the same thing >as a constant expression), it is also not a null-pointer constant. Wups. This is not my week. -- Imagine life with OS/360 the standard | Henry Spencer at U of Toronto Zoology operating system. Now think about X. | henry@zoo.toronto.edu utzoo!henry
rns@se-sd.SanDiego.NCR.COM (Rick Schubert) (10/04/90)
In <1990Oct3.172542.26794@zoo.toronto.edu> henry@zoo.toronto.edu (Henry Spencer) writes: >In article <3945@se-sd.SanDiego.NCR.COM> rns@se-sd.SanDiego.NCR.COM (Rick Schubert) writes: >>Since (""[0]) is not a compile-time value (I assume that's the same thing >>as a constant expression), it is also not a null-pointer constant. >Wups. This is not my week. In all fairness, though, this didn't occur to me until I saw your posting. -- Rick Schubert (rns@se-sd.sandiego.NCR.COM)
browns@iccgcc.decnet.ab.com (Stan Brown, Oak Road Systems) (10/05/90)
M> Followup-To: > Lines: 29 WARNING: Nit about to be picked. In <1990Sep28.144753.23727@zoo.toronto.edu> henry@zoo.toronto.edu (Henry Spencer) writes: >>In article <1990Sep27.131329.26616@phri.nyu.edu> roy@phri.nyu.edu (Roy Smith) writes: >>>... I meant to >>>write: >>> >>>#define NULL (""[0]) > >Roy, apart from not being a compile-time value, which limits its use, >this is exactly and precisely equivalent to > >#define NULL 0 Not exactly or precisely. Every time the first version is invoked, it creates a separate instance of a one-byte string. So you chew up static data storage. Depending on how your compiler does alignmnet, it may be two or four bytes each time--or more. And in large model with Microsoft C, some combinations of options could put each "" in its own data segment! Is that horse dead yet? Lord knows I've been beating it enough! :-) The above is my own opinion and not attributable to any other person or organization. email: browns@iccgcc.decnet.ab.com Stan Brown, Oak Road Systems, Cleveland, Ohio, U.S.A. (216) 371-0043
bls@u02.svl.cdc.com (Brian Scearce) (10/05/90)
browns@iccgcc.decnet.ab.com (Stan Brown, Oak Road Systems) writes: >>>In article <1990Sep27.131329.26616@phri.nyu.edu> > roy@phri.nyu.edu (Roy Smith) writes: >>>>#define NULL (""[0]) This is the same as #define NULL '\0' >>#define NULL 0 This is the same as #define NULL 0 Both are different from #define NULL (void *)0 Neither of the suggested #defines are guaranteed to work with not-all-bits-0-for-NULL implementations if you pass NULL as a parameter to a function with no prototype in scope. >Not exactly or precisely. Every time the first version is invoked, it >creates a separate instance of a one-byte string. There's that, too.
henry@zoo.toronto.edu (Henry Spencer) (10/05/90)
In article <26661@shamash.cdc.com> bls@u02.svl.cdc.com (Brian Scearce) writes: >This is the same as #define NULL '\0' >This is the same as #define NULL 0 > >Both are different from #define NULL (void *)0 > >Neither of the suggested #defines are guaranteed to work with >not-all-bits-0-for-NULL implementations if you pass NULL as a >parameter to a function with no prototype in scope. There is *no*, repeat *no*, definition of NULL that is guaranteed to work with not-all-bits-0-for-NULL implementations if you pass NULL as a parameter to a function with no prototype in scope. Actually, this is true even if null pointers are all-0-bits, because they may not all be the same size. Repeat after me, 512 times: The representation of different pointer types can be different. To turn NULL into a valid null pointer of a particular type, the compiler must know the exact type that is desired. In the absence of prototypes, the only way to give the compiler this information in function calls is to explicitly cast NULL to the desired type. No definition of NULL can ever remove the need for this, and lazy programmers are just going to have to learn to put the casts in. No legal program can tell the difference between #define NULL 0, #define NULL 0L, and #define NULL ((void *)0). (Even prototypes do not fully remove the need to be aware of this issue, since varargs functions still need the casts.) -- Imagine life with OS/360 the standard | Henry Spencer at U of Toronto Zoology operating system. Now think about X. | henry@zoo.toronto.edu utzoo!henry
henry@zoo.toronto.edu (Henry Spencer) (10/05/90)
I wrote: > No legal program can tell the difference between #define NULL 0, > #define NULL 0L, and #define NULL ((void *)0). Well, if you want to be really picky, something like "sizeof(NULL)" can, but no proper use of NULL as a pointer can. -- Imagine life with OS/360 the standard | Henry Spencer at U of Toronto Zoology operating system. Now think about X. | henry@zoo.toronto.edu utzoo!henry
mercer@npdiss1.StPaul.NCR.COM (Dan Mercer) (10/06/90)
In article <1990Oct2.040019.1635@ccu.umanitoba.ca> salomon@ccu.umanitoba.ca (Dan Salomon) writes: :In article <sazwbR600Vp6IHhVVV@andrew.cmu.edu> vd09+@andrew.cmu.edu (Vincent M. Del Vecchio) writes: :> I don't know about this. There are (unfortunately) still so many :> pre-ANSI compilers and so much pre-ANSI code (not to mention code that :> depends on the existence of the other "sins" that you mentioned) in use :> that it would be ridiculous for the time being to abandon backward :> compatibility. : :Much more code is going to be written in C than currently exists. :Should we sacrifice all the code to come for the sake of the existing :code? :-- : :Dan Salomon -- salomon@ccu.UManitoba.CA Regardless of what changes are made to the language there will always be problems for some in living within the languages limitations. The skill of a programmer is in coping with those difficulties. You cannot abandon previously written code and expect people to upgrade. However, not all the changes proposed would affect previously written code. For instance, implementation of a break label; capability would not affect previously written code. As for myself, I am more comfortable using flags (after getting burned by a nasty bug in PL1 code I wrote breaking out of a label). -- Dan Mercer Reply-To: mercer@npdiss1.StPaul.NCR.COM (Dan Mercer) "MAN - the only one word oxymoron in the English Language"