knowles@ccvaxa.UUCP (06/24/83)
#R:ccvaxa:8800003:ccvaxa:8800006:37777777600:353 ccvaxa!knowles Jun 22 21:19:00 1983 Thanks to those who alerted me to a C test suite in the possession of uiucdcs!richards (parsec!kolstad and parsec!fuka). We acquired the suite and have used it. Compiler people here say that its pretty good as far as it goes. Note that parsec!fuka also has a copy of the suite. Frankly, I'm surprised that this is the only suite that has surfaced....
suitti@CSvax:Pucc-H:pur-phy.UUCP (09/09/83)
My comment: You can eliminate the "cracks", within structures: If you assume that the order of items within a structure may be left to the compiler, then the compiler may sort the items into longest first. The reply: What you have, then, is not C-as-we-know-it. "Within a structure, the objects declared have addresses which increase as their declarations are read left-to-right." Removing that requirement would make life difficult for those of us who, for instance, read foreign (non-Unix) tapes directly into C structures, relying on the defined alignment of structures. My answer: Unless I looked at both machines's compilers carefully, and didn't really expect people to do this everywhere my programs were likely to be ported, I would never require that info sent/recieved would be in the structur's binary form. For instance, the binary byte order of a long is differant on a pdp-11 than a Vax! That blows that idea. How much more so is the whole structure likely to be differant? A related note, I've seen non-portable code of longs being played with using chars in several programs: The Gosling's EMACS info database routines for one. I re-read chapter 6 (structures) of K & R. There was no explicit statement that structure members would be in any order. When talking about the size of a structure it says: "But don't assume that the size of a structure is the sum of the sizes of it's members - because of alignment requirements for different objects, there may be "holes" in a structure." (chapter 6, page 130). It doesn't say how big the holes would be, etc. I can only think of one program on my system that would stop working if I hacked on the C compiler to sort by sizes (more on sorting later). That's the kernel. Structs are often used in device drivers to simplify the syntax of getting at all the various registers that the device has. There are a couple of fixes for that too. More comments: It would also make life more difficult when you decide to change a structure -- if you add a new object to an existing structure declaration you can simply read the old structure into the new one, set the value of the added object, and write it out again (you just specify different lengths on the read and write). More reply: This can be risky at best, and of limited use. If one has an array in the middle of a structure, expanding it or contracting it is going to upset things. This is one of the most common structure mods that I experience. Under my compiler (the Ritche v7 compiler), adding (or subracting) stuff at the end of the structure would be relatively safe. I prefer my programs to keep their data in ASCII while on disk, at least, they should have that capability. For one, it is easier to debug a clear-text data file. (I know, you never make mistooks). More comment: The whole scheme proposed also founders if objects within the structure do not have power-of-two lengths. If your structure contains a char[3] object, sorting it between length 4 and length 2 is not going to eliminate the need for an alignment byte. More reply: I should have thought more about the sorting procedure. The key to sorting should be the ls (least significant) bits of each "sizeof object". Start with those elements that have (for instance) their 3 ls bits zero. Then follow those objects with 2 ls bits, then with one zero ls bit, then the odd sized ones. Care should be taken that the sort is stable, that is, a structure will be sorted the same every time, so that separate compilation will still work. The UNIX kernel device driver's structures can be fixed in three ways. The first way is not to use structures for this purpose. The effort here would be unreasonable. There are many, many device drivers on many, many machines. The second fix is to have a command line switch to preserve order always. That way only the device drivers in the kernel need have "space - inefficient" structures. The third way is to leave structures alone that would not have holes in them as defined. This is probably safe. Device drivers use structures that have been carefully laid out. I doubt if there are any holes there anyway. I like the compile line switch, in general, for non-standard features. For instance, I wouldn't mind one for using single precision floating point for single precision. This can also be worked out. Stephen Uitti (physics site manager) ...pur-ee!Physics:suitti ...purdue!Physics:suitti
tll@druxu.UUCP (09/11/83)
The order of structure members is NOT arbitrary. The compiler must retain the order you specified. "Within a structure, the objects declared have addresses which increase as their declarations are read left-to-right." (C Reference Manual, p. 196) "Two structures may share a common initial sequence of members; that is, the same member may appear in two different structures if it has the same type in both and if all previous members are the same in both." (C Reference Manual, p. 197) This feature is used by many programs, and I don't think that closing the holes in a structure is worth removing this feature. Since compilers are not supposed to support == on structures, why doesn't a compiler give an error when you try instead of generating buggy code? Tom Laidig AT&T Information Systems Laboratories, Denver
franka@tekcad.UUCP (09/12/83)
#R:wateng:-27500:tekcad:17800003:000:586 tekcad!franka Sep 11 12:38:00 1983 Only certain machines REQUIRE allignment bytes (IBMs and PDP-11's spring immediately to mind). For example, int's and double's are alligned in VAX C only because of efficiency reasons. The hardware will fetch non- alligned data on certain machines (with an efficiency loss). Allignment of operands is not part of the language design, but only part of machine con- siderations. I would not say that the allignment of data is a reason not to allow rearrangement of structures, but having a consistent way to know where things are put is. Frank Adrian (tektronix!tekcad!franka)
preece@uicsl.UUCP (09/13/83)
#R:pur-phy:-91000:uicsl:6400009:000:3436 uicsl!preece Sep 12 08:56:00 1983 Further comments on altering the order of structure elements to eliminate alignment padding. I would never require that info sent/recieved would be in the structur's binary form. For instance, the binary byte order of a long is differant on a pdp-11 than a Vax! That blows that idea. --- Yes, it's a pain to have to worry about things like the byte order in longs. On the other hand, if the structure is long enough and has enough individual elements, it may be faster to explicitly change the byte order in the longs and use the rest of the structure. We recently had to read tapes carrying twenty different bibliographic databases, each in a different format, each consisting of records averaging perhaps a thousand bytes making up about twenty strings, forty longs, and various fixed location elements. The tapes ranged from 100K up to 10M records. Knowing the layout of the record structures we could manipulate only those parts that (1) we needed to use and (2) were not in the expected byte order. Having to copy the structures one element at a time would have been much slower, less clear, and would not have helped at all with the byte-order problem (some of the data on some of the tapes was in binary). --- I re-read chapter 6 (structures) of K & R. There was no explicit statement that structure members would be in any order. --- My quote is from page 196 (section 8.5 of the C Reference Manual, Appendix A of K&R). "Within a structure, the objects declared have addresses which increase as their definitions are read left-to-right." Seems unequivocal. --- I prefer my programs to keep their data in ASCII while on disk, at least, they should have that capability. For one, it is easier to debug a clear-text data file. (I know, you never make mistooks). --- I prefer to use ASCII files, too, when it's reasonable to do so. But sometimes it's not reasonable to do so. If you're dealing with a lot of numeric data it's not awfully efficient to be continually translating from ASCII back into binary. And efficiency is still sometimes an issue -- both because (at our site, at least) the machine is not free and because wall time is sometimes an issue. Ease of debugging is not the only thing that has to be considered, nor does the use of stored structures make debugging that much harder -- in our experience those structures are sometimes EXAMINED during debugging, but are rarely CHANGED by hand during debugging, so all you need is a simple filter to print out the contents of the file, in most cases. --- The second fix is to have a command line switch to preserve order always. That way only the device drivers in the kernel need have "space - inefficient" structures. The third way is to leave structures alone that would not have holes in them as defined. This is probably safe. Device drivers use structures that have been carefully laid out. I doubt if there are any holes there anyway. --- I could live with the command line option, though I'd make the current way the default to preserve compatibility with all the existing Unix programs in the world. The other idea is worse than the existing way, since it means that structures could be one way or the other. This could be painful in transporting software from one machine to another or in debugging after changing a structure definition. ---------- scott preece uiuc -- coordinated science lab pur-ee!uiucdcs!uicsl!preece
preece@uicsl.UUCP (09/22/83)
#R:wateng:-27500:uicsl:6400010:000:1049 uicsl!preece Sep 21 08:09:00 1983 Structure comparison can be very useful, but the nature of the comparison is almost always not simple enough to be handled by a built-in capability (except in the one case of testing for absolute equality). I would not want C to acquire abstract types with operations, but that's what you need if you want to have general structure operations. I wouldn't mind having a test for exact match of all named elements of structures included in C and I wouldn't mind having a structure assignment operation that set all named elements equal; both features would sometimes be useful and would involve only modest compiler effort. But I wouldn't say it was a very important gain, since we can write the tests explicitly or write them once and call them as a function. The ability to define exactly what we want comparisons of structures to do (whether we overload the existing relational operators or provide some other mechanism) would be very useful, but it doesn't fit into the texture of C, which is simplicity. scott preece pur-ee!uiucdcs!uicsl!preece
keesan@bbncca.ARPA (Morris Keesan) (09/29/83)
The C Reference Manual, as published in "The C Programming Language", by Kernighan and Ritchie, does indeed say (p. 197), "Two structures may share a common initial sequence of members . . . if . . . the same type in both and if all previous members are the same in both." HOWEVER, the revised C language, as of UNIX* System V, says (p. 92 of "Programming Guide UNIX* System), "The names of members and tags do not conflict with each other or with ordinary variables," and the System V "Transition Aids" says, in "User Level Changes to the C Language", "The C language has been revised to permit the reuse of structure members or field names," and also enforces strict type checking with regard to use of structure member names, including complete qualification of names. Given these changes, there is no need within the C language, i.e. in programs written only in C, for the preservation of the order of structures. The requirement for that is due to the nature of C as a system programming language, which must be able to interface with various operating systems, system services, and other languages, and must be able to create control
notes@ucbcad.UUCP (10/06/83)
#R:utzoo:-317600:ucbesvax:4800023:37777777600:702 ucbesvax!turner Sep 6 03:19:00 1983 Bravo, Mr. Spencer! Some years ago, when I was stuck on an RT-11 system, developing a graphics package, I inadvertently came to the same conclusion. With nothing but FORTRAN to use, and having been given Pavlovian anti-GOTO treatment in my introductory programming courses, I sought to minimize the use of GOTO by simply defining new procedures for use in "then" clauses, whenever these happened to be multi-line. (For "if...then...else", this didn't work, of course.) After a while, the code seemed to be restructuring itself to be more legible (at least to me.) If anything, C has gotten me OUT of this good habit. Well, I can't really blame the language for creeping vices... Michael Turner
bhyde@inmet.UUCP (01/24/84)
#R:vaxine:-15200:inmet:5000010:177600:1150 inmet!bhyde Jan 22 17:25:00 1984 This will work; f1, f2, and f3 are necessary. Of course I didn't want to have f1, f2, and f3, but then it occurs to me that this isn't Ada and suddenly I am happy. Ben Hyde, Intermetrics Inc. typedef int elem; /* An element */ typedef elem feature_vec[]; /* held in an array */ typedef feature_vec *features; /* with pointers to those arrays */ typedef features ftable[]; /* which are themselfs in an array. */ feature_vec f1 = {1,2,2,0}; feature_vec f2 = {2,3,0}; feature_vec f3 = {2,4,0}; ftable success = { (features)f1, (features)f2, (features)f3}; /* the casts are necessary or one gets warnings, why I don't know */ The zero element is being used here to mark the ends of a feature_vec, analogous to the zero element at the end of a string. Sam Haradhvala, my coworker here, said that in his application the ftable success was automaticly generated and that the set of all f1, f2, f3... overflowed one of the many target machine linkers. In such cases one can do: feature_vec f1 = {1,2,2,0, ,2,3,0, ,2,4,0}; ftable success = { (features)&f1[0], (features)&f1[4], (features)&f1[7]};
rpw3@fortune.UUCP (02/07/84)
#R:houxt:-35400:fortune:16200019:000:1050 fortune!rpw3 Feb 7 00:27:00 1984 Gee, we used to optimize loops like that with a 'DBcc', until the first time somebody tried to do more than 65536 things and discovered what the compiler person should have discovered before he ever hacked it in (it's o.k., he fixed it before we shipped it), namely: [From the 68000 User's Manual, Third Edition, page 115] "...If the termination condition is not true, the low-order 16 bits of the data counter are decremented by one..." Copying more than 256K bytes (65k longs) is not that uncommon these days. (How much memory does your system have?) If a "move word" was used to set up the counter (optimize! optimize!), you also get VERY strange results if the counter value gets used for anything inside the loop, regardless of the size of the count. Even with "move long", guess what prints about halfway through this: for( i = -10, i < 10, i++) printf("%d\n", i); Rob Warnock UUCP: {sri-unix,amd70,hpda,harpo,ihnp4,allegra}!fortune!rpw3 DDD: (415)595-8444 USPS: Fortune Systems Corp, 101 Twin Dolphins Drive, Redwood City, CA 94065
barrett@hp-dcde.UUCP (02/21/84)
What does that response have to do with net.lang.c?
johnl@haddock.UUCP (03/15/84)
#R:smu:13800001:haddock:12400004:177600:480 haddock!johnl Feb 13 15:18:00 1984 In regard to this: cat = foo ? fu = bar : mouse; Precedence has nothing to do with it. Precedence only matters when there are two possible legal parses, such as "a + b * c" which could be either "(a + b) * c" or "a + (b * c)" without precedence to disambiguate. The only possible parse for the first expression is: cat = foo ? (fu = bar) : mouse; so that the "fu = bar" assignment happens before the assignment to cat if it happens at all. Golly. John Levine, ima!johnl
mnc@hou2g.UUCP (#M.CONDICT) (03/19/84)
> In regard to this: > > cat = foo ? fu = bar : mouse; > > Precedence has nothing to do with it. Precedence only matters when there > are two possible legal parses, such as "a + b * c" which could be either > "(a + b) * c" or "a + (b * c)" without precedence to disambiguate. > > The only possible parse for the first expression is: > > cat = foo ? (fu = bar) : mouse; > > so that the "fu = bar" assignment happens before the assignment to cat > if it happens at all. Golly. What's wrong with the parse: (cat = foo) ? (fu = bar) : mouse; ? This evaluates an if-then-else expression containing two assignments as side effects and then throws away the result. Michael Condict ...!hou2g!mnc
jc@inmet.UUCP (05/05/84)
#R:nsc:-84400:inmet:5000015:177600:809 inmet!jc Apr 26 09:41:00 1984 Re: the 2nd-place winner of the Obfuscation contest. What's this supposed to do? On our VAX, its output is the following, where the 2nd and 3rd lines are the hex digits of the chars: '",x);_/*_\ 22272302205 72C89B9FAAC The other two programs were sorta cute, but this makes no sense. Aren't the winners supposed to do something interesting/entertaining? Maybe we got a garbled version of the program, or it doesn't work on a VAX? John M Chambers [inmet!jc] Intermetrics, Inc. 735 Concord Ave. Cambridge, MA 02138 "I don't have any solution but I certainly admire the problem."
jc@inmet.UUCP (05/05/84)
#R:nsc:-84500:inmet:5000016:177600:1295
inmet!jc Apr 26 11:38:00 1984
/*(The original form of this program, while technically impressive,
* nonetheless produced output containing unbalanced parentheses.
* We in the software business have enough of a reputation as
* illiterate slobs, without this sort of thing being openly
* rewarded! In an effort to encourage programmers to generate
* software that is more English-like and user-friendly, I submit
* the following modified version. :-)
*/
/* Portable between VAX11 && PDP11 */
short main[] = {
277, 04735, -4129, 25, 0, 477, 1019, 0xbef, 0, 12800,
-113, 21119, 0x52d7, -1006, -7151, 0, 0x4bc, 020004,
0x3A28, 10541, 2056, 04010, 4548, 3044, -6716, 0x9,
4407, 6, 5568, 1, -30460, 0, 0x9, 5570, 512, -30419,
0x7e82, 0760, 6, 0, 4, 02400, 15, 0, 4, 1280, 4, 0,
4, 0, 0, 0, 0x8, 0, 4, 0, ',', 0, 12, 0, 4, 0, '#',
0, 020, 0, 4, 0, 30, 0, 026, 0, 0x6176, 120, 25712,
'p', 072163, 'r', 29303, 29801, 'e'
};
/*
Original authors:
Sjoerd Mullender
Robbert van Renesse
Both @ Vrije Universiteit, Amsterdam, the Netherlands.
..!decvax!mcvax!vu44!{sjoerd,cogito}
Modified by:
John M Chambers [inmet!jc]
Intermetrics, Inc.
735 Concord Ave.
Cambridge, MA 02138
P.S. It took me less than 5 minutes to make and test this modification.
Top that, all you hackers!
*/
jc@inmet.UUCP (05/05/84)
#R:yale-comix:-347400:inmet:5000017:177600:343 inmet!jc Apr 26 15:02:00 1984 <> I ran this on a PDP-11 using Whitesmiths' C compiler, and got: 19 2 19 3 30 5 30 6 This seems almost correct, except for the truncation that turned the two 20s into 19s. John M Chambers [inmet!jc] Intermetrics, Inc. 735 Concord Ave. Cambridge, MA 02138 "I don't have any solution but I certainly admire the problem."
mpackard@uok.UUCP (05/13/84)
#R:smu:13800001:uok:3400002:37777777600:174 uok!mpackard May 13 13:06:00 1984 Concerning mr perry or ms perry, I never did determine the sex but it doesn`t matter because (s)he is on the rag! (s)he`s so smart that (s)he doesn`t have anyone to talk to.
bobm@zinfandel.UUCP (05/16/84)
#R:wivax:-1945700:zinfandel:14600018:177600:755 zinfandel!bobm May 14 23:18:00 1984 > 019 being equal to 17 decimal is an attribute of the VAX PCC lexer; > it is not a part of the C language definition. > > Without disregarding the many baroque qualities of the language > definition, one must realize that 'net.lang.c' is a newsgroup for > Talmudic dissection of Kernighan and Ritchie--weird questions are > expected. ANSI C should help clarify some of the ambiguities. > God help us when net.lang.ada really begins to be used! > -- > /Steve Dyer > decvax!bbncca!sdyer > sdyer@bbncca > /* ---------- */ K&R, Appendix A (the REAL reference; pay no attention to what it says in the chapters), Section 2.4.1, states, ".... The digits 8 and 9 have octal value 10 and 11 respectively...." Scholar of the Holy Law, Bob Miller
ajs@hpfcla.UUCP (06/10/84)
> isn't C++ == D??
Depends on the value of C.
Of course, 'C'++ == 'D', except the operation is illegal.
ado@elsie.UUCP (06/20/84)
> > isn't C++ == D?? > Depends on the value of C. > Of course, 'C'++ == 'D', except the operation is illegal. Actually, ++'C' == 'D', except the operation is illegal. -- ...decvax!allegra!umcp-cs!elsie!ado (301) 496-5688 (the DEC and VAX in decvax are Digital Equipment Corporation trademarks)
benk@inmet.UUCP (12/02/84)
How do I apply for maembership in the "Stamp Out BASIC Committee"? On second thought: how about a "Stamp out FORTRAN Committee"? On third thought: how about a "Stamp out PL/I Committee"? Ben Krepp (inmet!benk)
benk@inmet.UUCP (12/02/84)
If I'm not mistaken UTS C supports a 64 bit integer type; I believe that it is called a 'long long'. Not a bad idea at all. -- Ben Krepp (inmet!benk)
jans@mako.UUCP (Jan Steinman) (12/04/84)
Ben Krepp (<inmet.1852> benk@inmet.UUCP) says: > > How do I apply for maembership in the "Stamp Out BASIC Committee"? > On second thought: how about a "Stamp out FORTRAN Committee"? > On third thought: how about a "Stamp out PL/I Committee"? > It's called "ACM/SigAda, and they're also stamping out JOVIAL, CMS-2, and (deep breath) C. (Am I in the wrong newsgroup? Who's driving this bus?) (Send flames. Love mail.) -- :::::: Jan Steinman Box 1000, MS 61-161 (w)503/685-2843 :::::: :::::: tektronix!tekecs!jans Wilsonville, OR 97070 (h)503/657-7703 ::::::
Jeff Hanes (VLD/VMB) <jeffh@Brl-Vld.ARPA> (12/05/84)
> If I'm not mistaken UTS C supports a 64 bit integer type; > I believe that it is called a 'long long'. For that matter, how about a 128-bit floating point type? We could call it ... hmm, let's see ... how about: "double double" [toil and trouble, fire burn and ... ] (-: Sorry, couldn't resist that one :-). Thanks, Bill S., for that timely quote. -- Jeff Hanes
henry@utzoo.UUCP (Henry Spencer) (12/08/84)
Actually, there is a "long double" type in some of the recent ANSI C drafts... -- Henry Spencer @ U of Toronto Zoology {allegra,ihnp4,linus,decvax}!utzoo!henry
rpw3@redwood.UUCP (Rob Warnock) (01/15/85)
+--------------- | Nf-ID: #R:ea:5700031:uo-vax1:55600003:37777777600:180 | Nf-From: uo-vax1!bill Jan 9 19:10:00 1985 | | No, many people test ints, chars, etc. For example if i and j equal | 0x01 and 0x02 then i &= j gives i = 0, but i &&= j gives i = 1. | | Mark Aitken | {tektronix, hp-pcd}!uoregon!marka +--------------- Hmmm... K & R [p.46, p.191, & p.215] certainly doesn't list "&&=" as one of the legal operators, and the compiler I use (v.7 derived) doesn't hack it. A local addition, perhaps? Rob Warnock Systems Architecture Consultant UUCP: {ihnp4,ucbvax!dual}!fortune!redwood!rpw3 DDD: (415)572-2607 USPS: 510 Trinidad Lane, Foster City, CA 94404
bill@uo-vax1.UUCP (bill) (01/20/85)
No, many people test ints, chars, etc. For example if i and j equal 0x01 and 0x02 then i &= j gives i = 0, but i &&= j gives i = 1. Mark Aitken {tektronix, hp-pcd}!uoregon!marka
davee@hpgrla.UUCP (davee) (01/24/85)
/***** hpgrla:net.lang.c / cmu-cs-k!tim / 12:54 am Dec 11, 1984*/ Subject: Re: PCC and typedefs (why it barfs) The reason, incidentally, that PCC can't handle typedef identifiers properly is that they are recognized by the lexical analysis, not as identifiers, but as type keywords (like "int", etc.) /***/ It seems to me that in reading the recent ANSI C draft for the language, they are proposing doing exactly what you describe above. They have an entry in their YACC source for TYPEDEF instead of INDENTIFIER. This makes the YACC easier but may not do what people want for scoping. Refer to the YACC source posted to net.sources. Dave Ellis / HEWLETT-PACKARD hpda!hpfcla!hpgrla!davee
draves@harvard.ARPA (Richard Draves) (01/27/85)
> /***** hpgrla:net.lang.c / cmu-cs-k!tim / 12:54 am Dec 11, 1984*/ > Subject: Re: PCC and typedefs (why it barfs) > > The reason, incidentally, that PCC can't handle typedef identifiers properly > is that they are recognized by the lexical analysis, not as identifiers, but > as type keywords (like "int", etc.) > /***/ > > It seems to me that in reading the recent ANSI C draft for the language, > they are proposing doing exactly what you describe above. They have an entry > in their YACC source for TYPEDEF instead of INDENTIFIER. This makes the YACC > easier but may not do what people want for scoping. > > Refer to the YACC source posted to net.sources. > > Dave Ellis / HEWLETT-PACKARD > hpda!hpfcla!hpgrla!davee Recognizing typedef identifiers in the lexxer does not make it impossible to scope them properly; the parser should set a flag when it wants to disable this recognition. PCC sets this flag in the wrong places. Incidentally, I have never seen any other way of handling typedefs. Rich -- "If I am conceited, it is the conceit of an amazing man who has never found any surpassing himself." Al-Mutanabbi
jim@hpfcla.UUCP (jim) (02/15/85)
/***** hpcnoa:net.lang.c / rlgvax!geller / 8:38 am Jan 24, 1985*/ Subject: Re: c info (2nd request to a larger group) Without a doubt two of your finest MS-DOS "C" compilers are the LATTICE "C" compile (2.14 is the latest version) and the Wizard "C" compiler. I have been using the LATTICE compiler for more than 1 1/2 years. The documentation and the product are superb. As for an editor I could recommend no other editor than the new BRIEF editor from Solution Systems. The authors are on the net. BRIEF is an incredibly powerful editor that is a delight to use. It's MACROS programming language lets you do ANYTHING. Try them both out. I'd also recommend you try dealing with the Programmer Shop (ad in PC Tech Journal) as they provide you with gracious and professional service as well as allowing you to try various products without definite committments. I hope this is of some help to you or anyone else in need of some quality development software. I assure you that asside from being an extremely satisfied and happy developer I'm not associated with the above mentioned organizations. Have fun. David P. Geller {seismo}!rlgvax!geller /* ---------- */
jim@hpfcla.UUCP (jim) (02/15/85)
I will put in a good word for EDIX. It's really fast on my MSDOS machine (which does NOT have a graphics card) and has never crashed in over a year's use. It also has regular expression searches and the key bindings make sense (unless, of course, you've had too much vi to drink). My biggest gripe is the Emerging Tech folks don't seem to recognize their market and push the editor where it will do the most good. They seem more interested in the office market and I suspect EDIX is best loved by displaced UNIX hackers who have to use MSDOS for one reason or another.
dgary@ecsvax.UUCP (D Gary Grady) (02/21/85)
>> > > IS there a good C cross compiler which will >> > > produce 360-20 source assembly nmemonics? >> > Oh, like, wow. Are there still 360/20s around? If I remember correctly, IBM withdrew the 360/20 from the market around 1970. A typical 360/20 had 15K of core memory and a heavily microcoded half-word (16-bit) processor, making it the rough equivalent of a severely stripped-down PCjr. Forget about the maintenance charges (if maintenance is even available); the cost of power for the 360/20 probably exceeds the cost of a replacement system! Get a PC-XT. -- D Gary Grady Duke U Comp Center, Durham, NC 27706 (919) 684-3695 USENET: {seismo,decvax,ihnp4,akgua,etc.}!mcnc!ecsvax!dgary
preece@ccvaxa.UUCP (02/25/85)
> > > IS there a good C cross compiler which will > > > produce 360-20 source assembly nmemonics? > > > > Oh, like, wow. Are there still 360/20s around? > [followed by derogatory comments about the 360/20 instruction set] > I fail to see the purpose in responding to someone's request for > information in this manner. Do you really think that several > hundred thousand dollars, or a few million dollars, worth of > equipment is going to be thrown away every time someone comes > up with something new? I think the name for this kind of attitude > is "snobbery." ------------------- I don't know what the specifics would be for a 360-20, but for a lot of machines of even more recent vintage, you reach a point where the monthly maintenance charges are higher than the cost of a newer, more powerful machine. scott preece gould/csd - urbana ihnp4!uiucdcs!ccvaxa!preece
rs@mirror.UUCP (05/28/85)
Yeah, "an array==pointer" is at the heart of C, sort of. It is only true when "array" is being passed or received as a parameter. In this case, the C automatically changes all array names (e.g., foo(arr)) into addresses of the first element (e.g., foo(&arr[0])). Why? Well, I think history had something to do with it. The first versions of C had no structures or longs. Everything fit on the stack. 'You say arrays don't fit? Well then, let's just state that "array==pointer,"' I can hear the Wizard of New Jersey say, as they huddled around their pdp7... I think that B and BCPL (father and grandfather of C*) didn't really support arrays, just pointers and memory locations.
mike@hpdcdb.UUCP (mike) (06/27/85)
The chief reason pcc compilers cannot make intelligent register variable selection automatically is that they are single-pass compilers. Some kind of usage count is necessary to select candidates for register variables. By the time the compiler can accumulate a usage count, however, a single-pass compiler has already generated code. Automatically derived usage counts are invariably counts of static references. Such counts are useful but for my money I'd prefer dynamic usage counts. Consequently I've yet to see a compiler algorithm for automatic register variable selection that can beat explicit programmer selection. If anyone does have such an algorithm, please share it. Given the gutsy nature of C that allows the programmer great freedom to allocate registers as he sees fit, I would not be surprised at all if an automatic register allocator was greeted with loud cries of anguish from the programmer community. Register variables do alter the behavior of certain programs because the pcc compiler generates code sequences based on cost estimates. Since the use of register variables reduces the cost of certain subtrees it can change the order of evaluation in the generated code. The only situations I've seen where this matters is in the case of ambiguous source code constructs such as a[i] = a[i++]; I don't have a great deal of sympathy for anyone who gets different results depending on whether or not "i" is a register variable. K & R specifically warn about such constructs. Mike McNelly Hewlett-Packard Corp. hplabs!hpfcla!mike
oz@yetti.UUCP (Ozan Yigit) (07/05/85)
In article <504600001@hpdcdb.UUCP> mike@hpdcdb.UUCP (mike) writes: >The chief reason pcc compilers cannot make intelligent register variable >selection automatically is that they are single-pass compilers. Some kind >of usage count is necessary to select candidates for register variables. >By the time the compiler can accumulate a usage count, however, a >single-pass compiler has already generated code. VMS C compiler is essentially a single pass compiler also, (It performs the second pass if the program contains any case statements) yet, it is a well known REGISTER HOG !!! It will use every register, including AP, when it is available.. > >usage counts. Consequently I've yet to see a compiler algorithm for >automatic register variable selection that can beat explicit programmer >selection. If anyone does have such an algorithm, please share it. > Check out the DEC book on their PL/1 and C compilers. (I cannot remember the full title..) > >Given the gutsy nature of C that allows the programmer great freedom >to allocate registers as he sees fit, I would not be surprised at all >if an automatic register allocator was greeted with loud cries of anguish >from the programmer community. > I think the opinion is divided on that. Especially on RISC architectures, programmer could stifle the compiler from generating better code by not properly declaring the variables (assuming that the compiler is good old pcc, and does not use registers unless told). On the other hand, compiler should definately accept "advise" from the programmer, since henry@utzoo is so fond of reminding, compilers (and program beautifiers..) cannot read minds. Cornell tried to read minds at one time with their PL/C compiler. It did not work too well. >Register variables do alter the behavior of certain programs because >the pcc compiler generates code sequences based on cost estimates. Since >the use of register variables reduces the cost of certain subtrees it >can change the order of evaluation in the generated code. Is this an argument *for* or *against* the register variables ?? There is no question that certain optimization techniques may alter the order of evaluation by means of loop unrolling[1], or code motion out of loops[1], but under *no* circumstances should this provide a different result. Otherwise, compiler should be considered *broken*. >Mike McNelly [1] Bentley, Jon Luis, "Writing Efficient Programs", Prentice-Hall, 1982 -- Oz [all wizardesque side effects are totaly unintentional, unless stated otherwise..] Usenet: [decvax | allegra | linus | ihnp4] !utzoo!yetti!oz Bitnet: oz@ [yuleo | yuyetti] ------------- Support GNU. Consider the 3-muskateers' motto: ONE FOR ALL - ALL FOR ONE
guy@sun.UUCP (07/08/85)
> AT&T compilers these days all come with a tool, call "dis", for > disassembler. that look at object files and tell you exactly what > instructions are in them. Well, some AT&T compilers, anyway - the S5R2 documentation describes DIS(1) as "3B20 only". > This is neccessary because it is sometimes not possible to look at a > .s and tell exactly what instructions the assembler will produce. For > example an assembler might replace some long forms of jumps by short > forms. The PDP-11, VAX, and 68000 assemblers I've seen don't replace long jumps with short jumps; they replace a "generic" jump with a short or long jump. Then again, for the purposes of inspecting generated code to see "how good it is", this shouldn't make much of a difference; looking at the ".s" files should suffice. The disassembler may be useful for 3Bs; I believe they have a "generic" assembler language which translates into 3B20 or WE32000-series binary code. Guy Harris
faustus@ucbcad.UUCP (07/13/85)
> Let's say I am a person whose programming experience consisted a few > high school and college courses in Basic & Pascal. Ok, now let's say I > have a problem that I want solved by a programmer. The programmer comes > back to me with a program which doesn't do quite what I wanted. Now > from the comments it looks like the program should work right. The > problem is in the code. Now the programmer goes off and tries to fix > it, thinking he knows exactly what I want. But when he comes back with > the revised program, it still doesn't do what I wanted. Now the > comments were not enough to understand why the program doesn't do what I > wanted. Therefore I must look at the code ("Foul", I hear you say. > "What are you doing looking at his code; you're not an experienced C > programmer!" Well who else can look at it, if the programmer can't fix > it himself? At least I know what I want done). The program turns out > to be a full of these strange little idioms, which I've never seen > before. Luckily, some of the code is readable, so I hope that what is > wrong is in that. Let's say the problem with the program is that a > variable is being incremented when it shouldn't be. However I don't > know that the variable is being incremented because I see this cryptic > "stuff++" which I pretty much ignore because the code is full of things > like that which gets lost in the shuffle. I'm lost, the programmer > doesn't know what's wrong, and we're stuck. > > However if the program said "stuff = stuff + 1" or even > "increment(stuff)", I could say "Aha! I think I know why it's not > working. That variable 'stuff', why is it being incremented. I don't > think it should be incremented". The programmer removes that line, the > program is fixed, and we all live happily ever after. > > I know this was a rather long story, but I had to get my point across > somehow. Remember that the "I" in that story could be someone you will > be working for. You should either: (1) Hire programmers who do the right thing, or (2) Learn C. If there are nice features in a language like "i++", it is silly to expect programmers not to use them because non-programmers won't understand them. If you don't understand "i++", you sure won't understand "p->foo". Besides, many people have pointed out that you sometimes have to be a bit obscure to get efficient code -- if you write while (p->duck) p++; instead of while (p++->duck) ; you are likely not to get the loop compiled with auto-increment instructions... Anyway, you should admit that you are fighting a losing battle -- C programmers write programs that should be understood by and only by other C programmers, and if you don't know C you have no business trying to understand it. Wayne
ned@SCIRTP.UUCP (07/13/85)
> Progams should be as language-independent as possible. It shouldn't > matter whether the program is in C, Pascal, Ada, or even the dreaded > APL, but that it can be understood by *anyone* who needs to look at the > program. If you limit that *anyone* to "experienced C programmers", > you're limiting the possibilities of that program. > > Dan /* comments are of course welcome */ I disagree. If programs were written to be as "language-independent" as possible, what kind of languages would we be using??? Wouldn't this have the net effect of significantly slowing the evolution of computer language? I mainly program in C and Pascal, but I'm very glad that I had the opportunity to learn and use APL. It is a unique language with many good ideas. It is not perfect, but then no language is. It is not effective in all applications; no language that I'm aware of is. But I found it to be a refreshing, exciting, and fun(!) way to solve problems. Best of all, it made me a better programmer. The short-term benefits of *everyone* programming in compliance with the current popular semantic model are appealing, but the long-term results would be to retard the research and development of other forms of human/ computer communication. In light of the fact that many of today's problems cannot be adequately expressed to a machine, this would be a grave mistake. -- Ned Robie
bc@cyb-eng.UUCP (07/13/85)
I am surprised no one has mentioned "The Elements of Programming Style", by Kernighan and Plauger. It is an EXCELLENT book; I wish the world would read (and abide by) it. -- / \ Bill Crews ( bc ) Cyb Systems, Inc \__/ Austin, Texas [ gatech | ihnp4 | nbires | seismo | ucb-vax ] ! ut-sally ! cyb-eng ! bc
root@bu-cs.UUCP (07/13/85)
I remember teaching that strncpy hack...except it was: mvi str,c' ' mvc str+1(length-1),str hey, if you're gonna make it machine-dependant !MAKE IT MACHINE DEPENDANT! (where's my green card...) -Barry Shein, Boston University
lee@eel.UUCP (07/13/85)
The degree of readability of "if ((foo=..." is a reasonable subject of debate, but I decline to back down on the general assertion that one mark of a professional is a genuine effort to *maximize* readability, not just to bring it above some minimum threshold. As with any form of communication, there is no absolute scale on which to evaluate a speech, lecture, article or program as to its "readability", that is, the degree to which a person can absorb the information contained within it. People who teach writing and communication stress that the item MUST be designed with the expected audience in mind. An article written to explain FORTRAN to novice programmers will be inefficient (i.e. not maximally readable) to an experienced programmer. Likewise, programs "likely" to be read by expert programmers might well be more readable when "if ((fp=fopen..." is used even if for other programmers the opposite is true.
Kushall.henr@brl-tgr.UUCP (07/13/85)
DEC is selling the RD50 disk drive kits for Rainbow, Pro350 and DECmate for $750 as a close the 5 MB drives have beeb dropped. The Rainbow kit includes Controller, RD50 drive, Power Supply, CPM + MS-DOS operating systems. ED
ABN.ISCAMS@brl-tgr.UUCP (07/14/85)
Re getting the command line in CP/M-80: FACT - in Version 1, at least, of Turbo Pascal, Turbo eats everything after maybe the 30th or 31st character - puts a bunch of (consistent) garbage there. I have extensively tested this and am sorely tried by this particular bug! David P Kirschbaum Toad Hall AB.ISCAMS@USC-ISID
mike@hpfclq.UUCP (mike) (07/17/85)
Please don't garbage up net.lang.c for requests of "installation packages". Let's keep this notes group for language issues. Mike McNelly hplabs!hpfcla!mike
mer@prism.UUCP (09/11/85)
/* Written 11:50 am Sep 11, 1985 by rs@mirror.UUCP in prism:net.lang.c */ > We use the Lattice compiler here at Mirror Systems. > We purchased it through Unipress. > We have been using it for many months. > > BEWARE: Floating point has NEVER worked. We are getting real > ticked off... > Also, the linker blows up on large symbol tables > (seems to be whenever it's necessary to create a temp > file for it); we were told this one would take a > while. It's been a couple of weeks, already. > /* End of text from prism:net.lang.c */ Ummm, it's been more like *months*. Also, the latest version of the linker doesn't grok uppercase, but the file "OVERLAY.LIB" is hardwired into the code, so we're using an older version.
richw@ada-uts.UUCP (09/12/85)
I finally found the Lee paper and it's worth reading if you're serious about this stuff. It's pretty close to the code most recently posted, with some nice additions and good background, etc. My favorite improvement over the stuff I posted was the macro to declare Exceptions. It's something like: #define New_Exception(e) Exception e = "e"; Duh! I thought you couldn't do that (i.e. didn't think e would be replaced since it's in a string), but did I bother to TRY? Nooo... -- Rich
richw@ada-uts.UUCP (09/19/85)
I've been told that the ``feature'' allowing one to substitute a macro argument into a string is actually a common bug in C compilers which my C implementation suffers from, so be warned... -- Rich
marc@hpltca.UUCP (marc) (10/18/85)
Well, I own about 20 books on the topic, and by far and away the best one, in my opinion, is "Learning to Program in C", by Thomas Plum, published by Prentice-Hall. Plum has several more books, published this year, on such topics as how to write efficient C programs and reliable data structures. If I were going to do it all again, I'd buy everything Kernighan and Plum ever wrote and skip everything else. Marc Clarke, Hewlett-Packard, hplabs!hpfcla!hpltcb!marc
rs@mirror.UUCP (03/27/86)
A friend of mine recently did what you want. We were running UniPlus SysV on a 68000. He was doing image compression and needed to sample every n'th bit in a source, writing it out as the m'th bit in the destination. The 68000 "test bit specified by register X" was too slow, and he also wanted to unroll the loops. As I remember, the code went something like this: typedef int (*PFI)(); typedef short WORD; extern char *malloc(); PFI generate(count) int count; { WORD *base; WORD *p; base = p = malloc(sub_size); *p++ = prolog; /* he had the actual */ *p++ = prolog; /* hex words of the */ while (--count >= 0) { *p++ = test_bit; /* code here, not these */ *p++ = branch_if_zero .+2; /* "mnemonics" */ *p++ = mv 0,(a0); *p++ = skip; *p++ = mv 1,(a0); *p++ = decrement and branch if non-zero .-5; } *p++ = epilog; *p++ = return; return((PFI)base); } Then, in the main routine he had something like this: PFI *p, generate(); p =generate(5); (*p)(); I may have a cast or two slightly wrong, but the basic principle is sound. (Well, it worked, at any rate; I don't know how sound the basic principle really is :-) -- Rich $alz {mit-eddie, ihnp4!inmet, wjh12, cca, datacube}!mirror!rs Mirror Systems 2067 Massachusetts Avenue Cambridge, MA, 02140 Telephone: 6,176,610,777
dougm@ico (06/29/86)
/* Written 1:46 pm Jun 27, 1986 by rbutterworth@watmath.UUCP in ico:net.lang.c */ /* ---------- "Re: #if foo vs #if defined(foo)" ---------- */ > A CPP which silently takes undefined symbols to be 0 can be quite > dangerous. Consider the following case with these definitions ... > "#if squat||(3*y)". > I think the effort of having to use "#ifdef x" or "#if defined(x)" > instead of lazily using "#if x" is well worth it. I have to agree. Another sloppy practice I've come across is not using the "&&" and "||" but using "&" and "|" as equivalent to the doubled form. Then you end up spending time searching for a problem when someone changes a #define token to #define token 2 and having the #if token&token2 suddenly not work. Using the defined(token) construct when you only care about defined or not defined can save more time than the time it takes to type it in. Of course, you still have the people who think that #ifdef token&token2 does the same thing as #if defined(token)&&defined(token2)
karl@haddock (08/11/86)
[In the expression "cond ? voidf() : voidf()",] >The void values are not thrown away! True. They are being passed to the ?: operator. >Remember that (A?B:C) is an expression *returning a value*. Yes, it is an expression (as opposed to a statement); however, some expressions have type "void" (and no value). This is (or should be) one of them. >C is giving the error because it can't determine the type. No, it's giving the error because the compiler writer overlooked a case. I'm glad X3J11 has fixed this. Btw, a case where it could be useful (and where if...else won't do) is "(cond ? voidf0() : voidf1()), intf2())" used in an integer context. I admit I have no plans to use this feature in the near future, but it's a perfectly reasonable thing to allow. Karl W. Z. Heuer (ihnp4!ima!haddock!karl), The Walking Lint
karl@haddock (08/12/86)
dg_rtp!throopw (Wayne Throop) writes: >(As a small nit, I'd druther that the draft standard would allow a void > expression to be cast to void, but that's a fairly small quibble.) Void to void is illegal? Sonofagun, you're right, and they even made it explicit. How strange. Here's another restriction I just encountered: you can't typedef to void. This is probably because typedef is syntactically a storage class specifier, so it "looks like" an attempt to declare a void variable. I was trying to declare "typedef void dead;" so that I could distinguish between functions that return nothing (void perror(char *), setbuf(FILE *, char *), nullf(void)) from those that don't return (dead exit(int), abort(void), longjmp(jmp_buf, int)). Again, it's a small quibble; I'll just use #define instead. Karl W. Z. Heuer (ihnp4!ima!haddock!karl), The Walking Lint
aglew@ccvaxa.UUCP (08/15/86)
>I was trying to declare "typedef void dead;" so that I could distinguish >between functions that return nothing (void perror(char *), setbuf(FILE *, >char *), nullf(void)) from those that don't return (dead exit(int), >abort(void), longjmp(jmp_buf, int)). Again, it's a small quibble; I'll >just use #define instead. > >Karl W. Z. Heuer (ihnp4!ima!haddock!karl), The Walking Lint Good point, though - an optimizing compiler could take advantage of knowledge that a function doesn't return to do better register allocation, etc. Should this be in the langauge, or is a convention like if( error_condition ) { exit(1); /*NOTREACHED*/ } enough? (Rhetorical question: obviously, you should specify it at the point of declaration of such a function, not at the point of use.) Andy "Krazy" Glew. Gould CSD-Urbana. USEnet: ihnp4!uiucdcs!ccvaxa!aglew 1101 E. University, Urbana, IL 61801 ARPAnet: aglew@gswd-vms
karl@haddock (08/15/86)
mmintl!franka (Frank Adams) writes: [re the expression e1?e2:e3 where e2 and e3 are void] >It seems to me that there are two different paradigms for how to interpret >the ?: operator here. One is as an ordinary operator, which returns one of >the values of e2 or e3, depending on the value of e1. Under this >interpretation, it does not seem to me appropriate to permit e2 and e3 void, >since in that case they have no values. > >The other paradigm is that e1?e2:e3 is precisely one of e2 or e3 ... This >is a very reasonable interpretation; but [then it should preserve lvalues]. >In particular, one could write "e1?e2:e3 = e4;". I see your point. I think both voids and lvalues should be allowed, though the argument for the latter is less obvious. I've had a few occasions where I wanted to use a conditional lvalue, and had to settle for an if-else and a temporary variable (for e4). "*(e1?&e2:&e3) = e4;" doesn't work if one of e2 or e3 is a register or a bit-field, and it looks uglier. (Also, it tends to compile into "temp = e1 ? &e2 : &e3; *temp = e4;" rather than "temp = e4; e1 ? e2 = temp : e3 = temp;", at least on the machines I've tested.) Karl W. Z. Heuer (ihnp4!ima!haddock!karl), The Walking Lint
karl@haddock (08/16/86)
desint!geoff (Geoff Kuenning) writes: >While all of this discussion is very interesting and is important to >achieving a precise language definition, let us not forget that there >is *no* reason to ever write this particular expression. I already mentioned one: "(e1?e2:e3),e4". For another, the types might be unknown, if they are arguments in a macro; in this case I would want the macro to work on void as well as valued expressions. >[If-else] is better style anyway; it makes use of a construct that >people are much more used to, and it makes it clearer [what you are doing]. I won't argue that; though style is less important when you're writing a macro. Btw, I've been hacking at tail.c recently, and noticed that it has an expression statement of the form "flag ? f1() : f2()", where f1() and f2() are functions returning no value. The compiler accepted it, because they were (implicitly) declared int rather than void. Karl W. Z. Heuer (ihnp4!ima!haddock!karl), The Walking Lint
karl@haddock (08/20/86)
ccvaxa!aglew (Andy Glew) writes: >[haddock!karl (Karl Heuer) writes:] >>I was trying to declare "typedef void dead;" so that I could distinguish >>between functions that return nothing (void perror(char *), setbuf(FILE *, >>char *), nullf(void)) from those that don't return (dead exit(int), >>abort(void), longjmp(jmp_buf, int)). > >Good point, though - an optimizing compiler could take advantage of >knowledge that a function doesn't return to do better register allocation, >etc. Should this be in the langauge, or is a convention like /*NOTREACHED*/ >enough? (Rhetorical question: obviously, you should specify it at the point >of declaration of such a function, not at the point of use.) I posted this question before, and most of the response was on the order of "this declaration isn't NEEDED". True. But "void" wasn't necessary either; the language lasted quite some time with nonvalued int functions (which are still quite common, especially since "int" is the default datatype). The addition of "void" didn't improve the generated code of any compiler I know (the function and its caller both knew that no value was being used). As far as I can tell, it was added merely to allow clearer code, and to simplify catching certain kinds of errors. The same can be said of boolean expressions and dead functions. The only reasons for not adding them, as far as I can see, are as follows: [0] Inertia, of course. [1] It requires a new keyword (someone suggested that dead functions can be reuse the keyword "goto", but I don't think it's appropriate). [2] It won't be usable much. This is a valid point. There were a *lot* of nonvalued int functions before void was invented; there are only a handful of standard functions that are dead-ends. Booleans are more common, especially in programs like "ls" that have a flag for each option. But I digress. Returning to your comments: as for optimization, the calling function can take advantage of the knowledge by omitting extra branches (e.g. in "if (err) exit(1); else ...") or returns ("exit(0)" at the bottom of main()). This improves the space (but not time) efficiency, but not by much. I presume your comment about register allocation referred to the dead-end itself, in that the caller's registers need not be saved. I don't think you can assume this: the function "dead f() { for (;;) pause(); }" could be interrupted by a signal, whose handler could longjmp() to f's caller, whose registers must be recoverable. For similar reasons, it probably isn't okay to optimize the function call into a jump, unless you're careful with the stack. But I really hate having to write /*NOTREACHED*/ to keep lint happy! Karl W. Z. Heuer (ihnp4!ima!haddock!karl), The Walking Lint (Sorry if I've been rambling; it's late, and I should be in bed.)
bright@dataio.UUCP (Walter Bright) (08/22/86)
In article <86900019@haddock> karl@haddock writes: >ccvaxa!aglew (Andy Glew) writes: >>[haddock!karl (Karl Heuer) writes:] >>>I was trying to declare "typedef void dead;" so that I could distinguish >>>between functions that return nothing (void perror(char *), setbuf(FILE *, >>>char *), nullf(void)) from those that don't return (dead exit(int), >>>abort(void), longjmp(jmp_buf, int)). >> >>Good point, though - an optimizing compiler could take advantage of >>knowledge that a function doesn't return to do better register allocation, >>etc. > > The only >reasons for not adding [dead functions], as far as I can see, are as follows: > >[2] It won't be usable much. This is a valid point. There were a *lot* of >nonvalued int functions before void was invented; there are only a handful of >standard functions that are dead-ends. Functions that never return are used a LOT in code that is loaded with self-debugging assertion macros: #define assert(e) ((e) || printmsgandexit("e",__LINE__,__FILE__)) >As for optimization, the calling >function can take advantage of the knowledge by omitting extra branches (e.g. >in "if (err) exit(1); else ...") or returns ("exit(0)" at the bottom of >main()). This improves the space (but not time) efficiency, but not by much. > >I presume your comment about register allocation referred to the dead-end >itself, in that the caller's registers need not be saved. I don't think you >can assume this: the function "dead f() { for (;;) pause(); }" could be >interrupted by a signal, whose handler could longjmp() to f's caller, whose >registers must be recoverable. For similar reasons, it probably isn't okay >to optimize the function call into a jump, unless you're careful with the >stack. A good optimizer can make some important optimizations if it knows that a function will never return: 1) Register contents destroyed by the function call do not affect the caller. This has important ramifications when doing register allocation by coloring. 2) Functions are presumed to modify all globals and all indirect references. Thus, if the function does not return, the optimizer can find more common subexpressions, copy propagations, etc.
karl@haddock (08/22/86)
ttrdc!levy (Dan Levy) writes: >whatsa matter with "#define biff(pow) { if (pow) kayo(); else oof(); }"? Since biff is now a complete statement (no trailing semicolon required), you still can't write "if (...) biff(pow); else ...". You could leave out the semicolon, but this requires the user to know that biff is implemented this way. This is why the unusual definition "do {...} while (0)" (no trailing semicolon) has been offered. Ideally, it's nice for a macro to be an expression, since the function call it resembles is an expression. Thus ?: is preferred when possible. (It is evidently *not* possible in some compilers yet.) >Bright (et al) have been saying "change the definition of C to allow this." It's not clear whether this involves a change in the definition, or just a bug fix in some existing compilers. Karl W. Z. Heuer (ihnp4!ima!haddock!karl), The Walking Lint
franka@mmintl.UUCP (Frank Adams) (08/23/86)
In article <86900015@haddock> karl@haddock.UUCP writes: >... "(e1?e2:e3),e4". It occurred to me that there is a workaround which deals not only with the void case, but also with the case where the types of e2 and e3 are different (and the result is to be ignored): "e1?(e2,0):(e3,0)". I'm not sure whether to recommend this in cases where an expression is required instead of a statement, or to draw back in horror. >For another, the types might be >unknown, if they are arguments in a macro; in this case I would want the >macro to work on void as well as valued expressions. This case is not covered by my suggestion. I find it hard to imagine doing it, however. Frank Adams ihnp4!philabs!pwa-b!mmintl!franka Multimate International 52 Oakland Ave North E. Hartford, CT 06108
karl@haddock (09/03/86)
Note: In my earlier posting I came to the tentative conclusion that the "dead function" concept (a function which never returns, e.g. exit) would probably not be sufficiently useful to be worth adding a new builtin type. I haven't changed my mind; I just want to point out some possibilities. dataio!bright writes: >In article <86900019@haddock> karl@haddock writes: >>[2] It won't be usable much. This is a valid point. There were a *lot* of >>nonvalued int functions before void was invented; there are only a handful >>of standard functions that are dead-ends. > >Functions that never return are used a LOT in code that is loaded >with self-debugging assertion macros: > #define assert(e) ((e) || printmsgandexit("e",__LINE__,__FILE__)) But there are typically a very small number of such functions (usually one) per application. (Btw, I wouldn't want to assume that a dead function can be the right argument of "||".) >A good optimizer can make some important optimizations [with register usage, >information about global and indirect references] if it knows that a >function will never return. Good point. I hadn't thought of that type of optimization. Another "advantage" of an explicit declaration for dead functions is that, logically, one should be able to cast from "dead" into any other type -- a feature not available with "void". Since the code that would implement the cast is never reached, it need not do anything. This would allow extern double atod(); extern dead abort(); x = isfloatstr(s) ? atod(s) : abort(); which is a pretty bad example, so let me try again. "pointer to dead function" (I can't really call it "pointer to function returning dead", can I?) could be cast into "pointer to function returning T" for any type T. This would allow extern T f0(), f1(), f2(), f4(); extern dead abort(); T (*)() tab[] = { f0, f1, f2, abort, f4 }; Note that this can ALREADY BE DONE using an implicitly dead function. The functions in libc are declared "void" (that being the closest match), but it is perfectly legal to write double bomb(char *s) { write(2, s, strlen(s)); exit(1); } An explicit "dead" declaration, with permission to cast to other types, would seem to be more sensible. (Though I think I'd want to require the cast to be explicit.) Karl W. Z. Heuer (ima!haddock!karl; karl@haddock.isc.com), The Walking Lint (The opinions expressed above are not necessarily those of the author.)
karl@haddock (09/05/86)
killer!tad (Tad Marko) writes: >In my original article, ... I was asking if I should use >"foo(parm) char **parm; {...}" or "foo(parm) char *parm[]; {...}" >and I *DID* test both of them, and they both worked. Okay, that's a more sensible question. The official truth is that in this context, they are equivalent. However, my *personal opinion* is that the former is "more correct"; the latter is a kludge where the compiler figures out what you "must have really meant" and converts it for you. (Kind of like how some compilers will interpret "&a" as "&a[0]" if "a" is an array, though in that case you'll probably get a warning at least.) My recommendation is to write "char **parm"; it causes less confusion. Even if you do write "char *parm[]", you are declaring a pointer, not an array. (Similarly, a formal argument declared "float parm" really declares a double, which is also quite confusing, e.g. if you take its address.) Oh yes, some compilers used to consider a parameter declared "type x[]" to be a *non-modifiable* pointer to type. That no longer seems to be popular. Karl W. Z. Heuer (ima!haddock!karl; karl@haddock.isc.com), The Walking Lint
jsdy@hadron.UUCP (Joseph S. D. Yao) (09/11/86)
In article <1761@mmintl.UUCP> franka@mmintl.UUCP (Frank Adams) writes: >>For another, the types might be >>unknown, if they are arguments in a macro; in this case I would want the >>macro to work on void as well as valued expressions. >This case is not covered by my suggestion. I find it hard to imagine doing >it, however. When would one try to pass a void "value" to anything, whether or not it is a macro? (I agree, that is v e r y hard to imagine!) -- Joe Yao hadron!jsdy@seismo.{CSS.GOV,ARPA,UUCP} jsdy@hadron.COM (not yet domainised)
karl@haddock (09/17/86)
hadron!jsdy (Joe Yao) writes: >In article <1761@mmintl.UUCP> franka@mmintl.UUCP (Frank Adams) writes: >>[haddock!karl (Karl Heuer) writes:] >>>For another, the types might be >>>unknown, if they are arguments in a macro; in this case I would want the >>>macro to work on void as well as valued expressions. >>This case is not covered by my suggestion. I find it hard to imagine doing >>it, however. >When would one try to pass a void "value" to anything, whether or >not it is a macro? (I agree, that is v e r y hard to imagine!) Your comment "whether or not it is a macro" suggests that you are assuming the macro has function semantics, in which case it would not be useful to hand it a void expression. But not all macros have this property; consider #define new(T) ((T *)malloc(sizeof(T))) which expects a type rather than an expression. What I was thinking of (I don't have a specific instance) was a macro whose return value has the same type as its arguments -- like generic MIN and MAX. To concoct something that would accept void arguments, you could write #define foo(e1,e2) (SOMETHING ? (SOMETHING,(e1)) : (SOMETHING,(e2))) I suppose. Of course, the user must be aware that this is a macro, and that its value is void when its arguments are. In any case, I agree that it's not all that likely, but it's not inconceivable. Karl W. Z. Heuer (ima!haddock!karl; karl@haddock.isc.com), The Walking Lint