PETERSC0%VUCTRVAX.BITNET@wiscvm.wisc.EDU (07/17/87)
I'm sure I'll get jumped on for this, but what the heck... As far as I am concerned there is no justification (unless you know that one form is clearly better than the other for your compiler and machine) to use ++index over index++ (or vice versa). Since my latest project is being written in Pascal (grumble, grumble, no C for our main VAXen), I long for either or both of these functions! I forgot to mention one other case to be made for one or the other of the above, if your program/sub-program depends on which way it goes, it obviously makes a difference... The main quibble I have with C programmers (none of you, of course) in general is that they get carried away with the famed terseness and compact- ness of C. They tend to compact their valiables and declarations and everything that they control until it is (often) unreadable to most non- gurus. It may be my heritage as a Pascal (and even Cobol) programmer or the fact that my prof.s are killing me with 'style' issues, but I like to know what the program means at a glance... I really only see two classes of style issues. The first is the issue of whether or not you make your names/definitions clear. The second is how you place your grouping symbols (begin/end and {/}) and how far you squash your statements (1/line or 10/line). The rest (except for comments, which I won't go into) is personal... The fire-retardent suit is on, so flame away... Chris Petersen petersc0@vuctrvx1.bitnet "Dr. Tachyon, I presume?"
jfjr@mitre-bedford.arpa (Freedman) (04/26/88)
C provide tags and typdefs ie I can make the following declaration struct some_tag_name { some_more_stuff } or typedef struct { some_stuff } some_type_name. I can do similar things with enum. Now, as a former Pascal programmer I like the typedef method MUCH better than the tag method. My question is this: Is there any reason one method is preferred over the other? (except for declarations for structure which will include pointers -for trees, lists,etc) Jerry Freedman, Jr "Love is staying up all night jfjr@mitre-bedford.arpa with a sick child, (617)271-4563 or a healthy adult"
gwyn@brl-smoke.ARPA (Doug Gwyn ) (04/27/88)
In article <13115@brl-adm.ARPA> jfjr@mitre-bedford.arpa (Freedman) writes: > Now, as a former Pascal programmer I like the typedef method >MUCH better than the tag method. My question is this: Is >there any reason one method is preferred over the other? Typedef was added to C after struct tags. For the most part it is more convenient to use typedef. Sometimes it is easier to use tags, though, as in struct my_tag { struct my_tag *link; data_t data; };
tps@chem.ucsd.edu (Tom Stockfisch) (04/27/88)
In article <7770@brl-smoke.ARPA> gwyn@brl.arpa (Doug Gwyn (VLD/VMB) <gwyn>) writes: >In article <13115@brl-adm.ARPA> jfjr@mitre-bedford.arpa (Freedman) writes: >> Now, as a former Pascal programmer I like the typedef method >>MUCH better than the tag method... >Typedef was added to C after struct tags...Sometimes it is easier to >use tags, though, as in > struct my_tag { > struct my_tag *link; > data_t data; > }; In this case you can use typedef struct LIST { struct LIST *link; data_t data; } LIST; since tags and typedefs are in different overload classes. This usage is not strange looking if you think of the initial "struct LIST" as meaning "BEGIN LIST DECLARATION" and the final "LIST;" as "END LIST DECLARATION". -- || Tom Stockfisch, UCSD Chemistry tps@chem.ucsd.edu
dsill@nswc-oas.arpa (Dave Sill) (04/28/88)
Tom Stockfisch writes: >In this case you can use > > typedef struct LIST { > struct LIST *link; > data_t data; > } LIST; > >since tags and typedefs are in different overload classes. >This usage is not strange looking if you think of the >initial "struct LIST" as meaning "BEGIN LIST DECLARATION" >and the final "LIST;" as "END LIST DECLARATION". Yuck. Although legal, taking advantage of separate name spaces like this is material for Obfucated C Code Contest entries. This example also comflicts with the popular convention of using uppercase-only names for macros. ========= The opinions expressed above are mine. Trivia Question: What is the origin of `uppercase'?
tps@chem.ucsd.edu (Tom Stockfisch) (04/29/88)
In article <13154@brl-adm.ARPA> dsill@nswc-oas.arpa (Dave Sill) writes: >Tom Stockfisch [THAT'S ME] writes: >>In this case you can use >> >> typedef struct LIST { >> struct LIST *link; >> data_t data; >> } LIST; >> >>since tags and typedefs are in different overload classes. >>This usage is not strange looking if you think of the >>initial "struct LIST" as meaning "BEGIN LIST DECLARATION" >>and the final "LIST;" as "END LIST DECLARATION". > >Yuck. Although legal, taking advantage of separate name spaces >like this is material for Obfucated C Code Contest entries. Everyone's entitled to their opinion. This is, however, essentially what happens in C++, where you get an automatic typedef of the same name for every struct tag. Are you saying that you would want to save the tag for a different use, as in typedef int LIST; struct LIST { ... }; ? If not, why object? >This example also comflicts with the popular convention of using >uppercase-only names for macros. For better or for worse, there are many different conventions for upper/lower case and capitalized/uncapitalized. I quit using lower case names for typedefs after running into the pcc bug (I've been told it's in all pcc compilers and will never be fixed) in which local (auto) declarations do not hide outer typedef names, even tho this is guaranteed in K&R p. 206 (1st ed.): typedef float distance; ... { auto int distance; The above won't work on my compiler. Hence, the all-caps for typedefs. -- || Tom Stockfisch, UCSD Chemistry tps@chem.ucsd.edu
throopw@xyzzy.UUCP (Wayne A. Throop) (12/16/88)
In the code fragment posted in this line of conversation, there was one "style fault" that could actually qualify as a bug under draft X3J11, and which therefore I felt ought to be pointed out. Now when I got done with the posting, I found I had picked on four more points of style in the code fragment, and my posting had ended up looking like a hatchet job rather than a warning of a nonportable practice. Well, rather than pare down my nits to the most important one, I'm posting the whole critique. I hope folks won't take this as the hatchet job it superficially resembles, but will take in the way it was intended: an important warning followed by four stylistic afterthoughts that I really and truely think result in code of "superior style". Happy coding, and if you feel I've been too harsh despite the disclaimer, feel free to email me and vent your spleen. The fragment in question is: void strupr( s ) char s[]; { int p = 0; while ( s[p] != NULL ) { s[p] = toupper( s[p] ); p++; } } /* strupr */ My comments, in decreasing order of urgency (or increasing order of pickiness) are these. First, comparing a character to NULL is stylistically wrong in K&R C, since NULL is to be used in pointer contexts (just as FALSE or NO or whatnot is to be used in "boolean" contexts). In draft X3J11 C, this is even a potential error, since NULL can legitimately be defined as ((void *)0), in which case an implementation (I think) is allowed to diagnose an error in the above comparison. Second, the loop control is scattered over the body of a while, which is exactly what the for loop was invented for. Third, the function might as well return s instead of void, so that it can be slipped unobtrusively into expressions instead of forcing separate statements or awkward expressions. Fourth, it isn't indicated that ctype.h ought to be included. (This is, of course, fairly obvious, and may have been omitted on purpose...) Fifth, the object of this excersize is somewhat more naturally cast in terms of pointers rather than subscripting in C. Two marginal justifications for this are that first it is more natural to step along an array once by pointers, and second compilers with few or no optimizing smarts will generate better code for the pointer case on most (but not all) architectures. (This, of course, is a really picky, obnoxiously finicky nit.) Applying all of these, we get the "improved" fragment (using prototypes): #include <ctype.h> char *strupr( char *s ) { register char *p; for( p=s; *p != '\0'; p+=1 ) *p = toupper( *p ); return( s ); } Note that some might prefer the condition in the for loop to be *p != 0 or just *p (In fact, I prefer just *p myself, but most folk seem to prefer the explicit comparison to a character value.) -- "Leave him alone. He is already neutralized." "I don't want neutral. I want dead." --- exchange in "Die Hard" -- Wayne Throop <the-known-world>!mcnc!rti!xyzzy!throopw
msb@sq.uucp (Mark Brader) (12/20/88)
Wayne A. Throop (throopw@xyzzy.UUCP) made, in <2404@xyzzy.UUCP>, some criticisms of a certain piece of code including these lines: > > int p = 0; > > while ( s[p] != NULL ) { The last of these was: > Fifth, the object of this exercise is somewhat more naturally cast in > terms of pointers rather than subscripting in C. Wayne went on to cite two admittedly minor justifications for this. And I'd like to add another: avoiding the use of "int" for the subscript! Remember that "int" is allowed to be as small as 16 bits. It is quite conceivable that s[] has more than 32767 elements in it, so p can overflow, followed by God-knows-what (or as the X3J11 people say, by "undefined behavior"). A similar problem can exist if we make p "unsigned"; in this case it would be an infinite loop. On the other hand, some compilers wouldn't allow the object's dimension to exceed an int's range, so declaring p as "long" could be wasteful. If we use pointers instead of subscripts to step through the array, no such problem can exist. A pointer that points to the beginning of an array is guaranteed to be incrementable to the end of the array (plus one more time, in Draft ANSI C); and there is only one size of pointer variable (in true C, anyway): the right size. Mark Brader "Those who do not understand UNIX SoftQuad Inc., Toronto are condemned to repeat it." utzoo!sq!msb, msb@sq.com -- Henry Spencer
throopw@xyzzy.UUCP (Wayne A. Throop) (12/29/88)
As larger nits have lesser nits Upon their backs to bite 'em, The lesser have still lesser nits, And so ad infinitum. Chris Siebenmann (ziebmef!cks) reminds that my "correction" of an earlier code fragment is itself flawed. I had a loop as #include <ctype.h> char *p, *s; ... for( p = s; *p; ++p ) *p = toupper( *p ); Nearly as I can tell, dpANS says that loop ought to have been for( p = s; *p ++p ) if( *p >= 0 ) *p = toupper( *p ); because all functions defined in ctype.h take arguments that are integers, but give defined results only if those integers have values representable as unsigned integer (or are the constant EOF). Thus, the test for negative values is (I *think*) necessary. Unless, of course, you are willing to otherwise ensure that s only points at strings of vanilla characters... then the loop is OK as it was. -- The program itself is the only complete description of what the program will do. --- P.J. Davis -- Wayne Throop <the-known-world>!mcnc!rti!xyzzy!throopw
peter@ficc.uu.net (Peter da Silva) (12/30/88)
In article <2537@xyzzy.UUCP>, throopw@xyzzy.UUCP (Wayne A. Throop) writes: > #include <ctype.h> > char *p, *s; > ... > for( p = s; *p; ++p ) > *p = toupper( *p ); > Nearly as I can tell, dpANS says that loop ought to have been > for( p = s; *p ++p ) > if( *p >= 0 ) > *p = toupper( *p ); Gee, I always do this: for(p = s; *p; p++) if(islower(*p)) *p = toupper(*p); While dpANS might have decided that toupper should bounds check, there are too many V7-oid compilers out there that it's better to put the bounds check in. Personally, I think that toupper should have been left the way it was. Everything else in stdio forces you to do your own bounds checking, so why should this be an exception? -- Peter da Silva, Xenix Support, Ferranti International Controls Corporation. Work: uunet.uu.net!ficc!peter, peter@ficc.uu.net, +1 713 274 5180. `-_-' Home: bigtex!texbell!sugar!peter, peter@sugar.uu.net. 'U` Opinions may not represent the policies of FICC or the Xenix Support group.
bdb@becker.UUCP (Bruce Becker) (12/30/88)
In article <2537@xyzzy.UUCP> throopw@xyzzy.UUCP (Wayne A. Throop) writes: >[...] > for( p = s; *p ++p ) > if( *p >= 0 ) > *p = toupper( *p ); > >because all functions defined in ctype.h take arguments that >are integers, but give defined results only if those integers have >values representable as unsigned integer (or are the constant EOF). > >Thus, the test for negative values is (I *think*) necessary. Unless, >of course, you are willing to otherwise ensure that s only points at >strings of vanilla characters... then the loop is OK as it was. I'd like to point out a (possibly icky) variant - for( p = s; *p ++p ) *p = toupper( *p&0xff ); This gets at possible 256-character sets in the environments where the compiler &/| hardware has sign-extended the negative byte value. Not all _ctype arrays have the same range - some are only 128 bytes. In those cases the '0xff' above becomes '0x7f'. It might be useful to add that testing for EOF is possible - this raises the question of its value. Ought it to be -1, or 0xFF, or what? I'm confused about what the value of "toupper(EOF)" should be... >Wayne Throop <the-known-world>!mcnc!rti!xyzzy!throopw Cheers, -- _ _/\ Bruce Becker Toronto, Ont. \`o O| Internet: bdb@becker.UUCP, bruce@gpu.utcs.toronto.edu \(")/ BitNet: BECKER@HUMBER.BITNET ---mm-U-mm--- "The OSF is suffering from Penix envy" - Rocky Raccoon
gwyn@smoke.BRL.MIL (Doug Gwyn ) (01/02/89)
In article <189@becker.UUCP> bdb@becker.UUCP (Bruce Becker) writes: > It might be useful to add that testing for EOF is > possible - this raises the question of its value. > Ought it to be -1, or 0xFF, or what? I'm confused > about what the value of "toupper(EOF)" should be... EOF is not required to be defined as -1, but that is really the most practical choice in every environment I've seen. It must NOT be the same as a possible character value, so 0xFF is wrong. I don't think EOF is supposed to be a valid argument for toupper(), just for the is*() functions.
bill@twwells.uucp (T. William Wells) (01/06/89)
In article <2581@ficc.uu.net> peter@ficc.uu.net (Peter da Silva) writes: : In article <2537@xyzzy.UUCP>, throopw@xyzzy.UUCP (Wayne A. Throop) writes: : > #include <ctype.h> : > char *p, *s; : > ... : > for( p = s; *p; ++p ) : > *p = toupper( *p ); : : > Nearly as I can tell, dpANS says that loop ought to have been : : > for( p = s; *p ++p ) : > if( *p >= 0 ) : > *p = toupper( *p ); : : Gee, I always do this: : : for(p = s; *p; p++) : if(islower(*p)) : *p = toupper(*p); : : While dpANS might have decided that toupper should bounds check, there : are too many V7-oid compilers out there that it's better to put the : bounds check in. Personally, I think that toupper should have been left : the way it was. Everything else in stdio forces you to do your own bounds : checking, so why should this be an exception? There are two distinct issues: 1) The signedness of a character. 2) The range checking of islower/toupper. If the character array may contain any character which is not guaranteed to have a positive value, the *p may generate a negative value. This will blow away many if not most islower's and toupper's. This means that if that possibility exists, one must either use unsigned characters or handle the negative values which may be produced. Once one has made sure that no negative values will make it into toupper, one must also handle the case of toupper's that don't work unless the character is a lower case letter. This means using something like islower as well. Combining the two code fragments above, the one with the sign test, and the one with the islower test, will produce code that works for all situations. --- Bill { uunet!proxftl | novavax } !twwells!bill
imp@Solbourne.COM (Warner Losh) (01/16/91)
In article <12075.279314fc@ecs.umass.edu> gerst@ecs.umass.edu writes: >CDC uses quite a nice style for everything in their NOS/VE operating >system. For what it is worth, VMS does the same sort of things (although the details vary slightly). I found it useful when I was hacking in MACRO-32, but less useful in 'C'. The best reason to do it is that you don't polute the user's name space, which is a growing problem in C (and various add on libraryies). Warner -- Warner Losh imp@Solbourne.COM We sing about Beauty and we sing about Truth at $10,000 a show.