gwyn@brl-smoke.ARPA (Doug Gwyn ) (04/30/86)
In article <838@ihwpt.UUCP> knudsen@ihwpt.UUCP (mike knudsen) writes: >Has anyone else noticed that Boolean types and operators >have less than full citizenship in C? Examples: >... >(3) There is no boolean data type. No big gripe; >lots of us say "typedef short bool" in our .h files. Technically, there are no true Boolean data types in C. Ints (NOT shorts) are made to serve when a Boolean would be called for. I have always considered this a deficiency, but (except for getting "lint" to cooperate) it can be remedied by the programmer being careful to keep Boolean usages distinct from integer usages. For example, treat the result of a relational expression as Boolean, not as a 1 or a 0. I find that carefully maintaining the distinction contributes to code correctness and maintainability. I generally frown on C language extension via the preprocessor (as in a recent Byte article), but I make an exception for Booleans. The same standard header file that I mentioned a few days ago (that defines "void" for machines that don't have it, etc.) contains the following: typedef int bool; /* boolean data */ #define false 0 #define true 1
flip@osu-cgrg.UUCP (Flip Phillips) (04/30/86)
[ ... boolean gripes ... ] > > (3) There is no boolean data type. No big gripe; > lots of us say "typedef short bool" in our .h files. typedef char bool; uses less space on some machines. -- Flip Phillips {ucbvax,decvax}!cbosg!osu-cgrg!flip Computer Graphics Research Group, The Ohio State University
kwh@bentley.UUCP (KW Heuer) (04/30/86)
In article <838@ihwpt.UUCP> ihwpt!knudsen writes: >(1) Found out this weekend that you can't say: > boolvar ||= boolean_expression An interesting expression. The left side of the assignment would have to be evaluated first, and if already set, do nothing. I presume the reason this is omitted is because it's normally written "if (v || e) v=1;" or "if (!v && e) v=1;" rather than "v = v || e". Btw, you can't have *all* operators extended with "=". How would you write "v = v < e;"? (Not that it's useful.) >(2) There isn't any ^^ (XOR) operator either, as in > if(divisor <0) ^^ (dividend <0) > quotient = -quotient; There is, but it's spelled "!=". (Presumably more efficient than "^", though I think either one should work with a smart compiler.) >(3) There is no boolean data type. No big gripe; >lots of us say "typedef short bool" in our .h files. I'd assume either "char" (for space) or "int" (for time). "short" probably gives you the worst of both worlds. However, a true boolean datatype would have a couple of advantages: o Multiple flag variables with local scope and no address operator (e.g. variables declared "register bool") could be packed into a single word. o "++x" and "--x" could be defined as "set" and "clear"; "x++" and "x--" would then be "test and (set|clear)". This would obviate such things as "if (!flag) { flag=1; printmsg(); }". Karl W. Z. Heuer (ihnp4!bentley!kwh), The Walking Lint
tps@sdchem.UUCP (Tom Stockfisch) (05/03/86)
In article <778@bentley.UUCP> kwh@bentley.UUCP writes: >In article <838@ihwpt.UUCP> ihwpt!knudsen writes: >>(2) There isn't any ^^ (XOR) operator either, as in > >There is, but it's spelled "!=". (Presumably more efficient than "^", though >I think either one should work with a smart compiler.) > Not quite the same. 3 ^^ 4 would evaluate as 0, 3 != 4 evaluates as 1. -- Tom Stockfisch, UCSD Chemistry
jimc@ucla-cs.ARPA (Jim Carter) (05/03/86)
In article <778@bentley.UUCP> kwh@bentley.UUCP (KW Heuer) writes: >Btw, you can't have *all* operators extended with "=". How would you write >"v = v < e;"? (Not that it's useful.) I think it's useful! As written, of course, it's semantically invalid, but what you really mean is "v <= e" (sic) or, to demonstrate where it's really useful, array[horrendous] [subscript] [list] <= bigexpr; rather than if (array[h][s][l] < bigexpr) array[h][s][l] = bigexpr; Now "<=" already means something else so this syntax is not acceptable. How about "v < = e" with a mandatory blank? This is atrocious human engineering but at least is parseable. Anybody have any better ideas? -- James F. Carter (213) 206-1306 UCLA-SEASnet; 2567 Boelter Hall; 405 Hilgard Ave.; Los Angeles, CA 90024 UUCP:...!{ihnp4,ucbvax,{hao!cepu}}!ucla-cs!jimc ARPA:jimc@locus.UCLA.EDU
greg@utcsri.UUCP (Gregory Smith) (05/03/86)
In article <778@bentley.UUCP> kwh@bentley.UUCP (KW Heuer) writes: >In article <838@ihwpt.UUCP> ihwpt!knudsen writes: >>(1) Found out this weekend that you can't say: >> boolvar ||= boolean_expression > >An interesting expression. The left side of the assignment would have to be >evaluated first, and if already set, do nothing. I presume the reason this is >omitted is because it's normally written "if (v || e) v=1;" or "if (!v && e) >v=1;" rather than "v = v || e". > Interesting - I was going to suggest if(e)v=1; but that's not the same thing. I was surprised to find out recently that ` i >> = 1 ' is legal, as opposed to `>>='. I really think this should produce at least a warning. (4.2BSD) > >>(2) There isn't any ^^ (XOR) operator either, as in >> if(divisor <0) ^^ (dividend <0) >> quotient = -quotient; > >There is, but it's spelled "!=". (Presumably more efficient than "^", though >I think either one should work with a smart compiler.) If I had $0.02 for everything that people have said should be done by a smart compiler... :-) :-) I know, that's what compilers are for. But it's not quite the same thing. 2 ^^ 1 should be 0, and 2!=1 is 1, and 2^1 is 3. Of course, in the example given, that won't happen. In any case, you can always say !a != !b. On the subject of operators, someone said a while back that they had a compiler with commented-out code to support '/\' and '\/' ( max and min ) operators - and that they had qualms about activating it and then writing non-portable code. I suggest that they activate it, and then write #define min(a,b) ((a)\/(b)) #define max(a,b) ((a)/\(b)) in a header, to allow portability. Presumably, the code produced by these operators should be somewhat better than a>b?a:b. Of course, you still have to avoid writing min( array[atoi(x1)], i+cindex[getc(file)]) :-). -- "For every action there is an equal and opposite malfunction" ---------------------------------------------------------------------- Greg Smith University of Toronto UUCP: ..utzoo!utcsri!greg
kwh@bentley.UUCP (KW Heuer) (05/05/86)
In article <778@bentley.UUCP> I wrote: >A true boolean datatype would have a couple of advantages: > >o Multiple flag variables with local scope and no address operator (e.g. > variables declared "register bool") could be packed into a single word. > >o "++x" and "--x" could be defined as "set" and "clear"; "x++" and "x--" > would then be "test and (set|clear)". This would obviate such things as > "if (!flag) { flag=1; printmsg(); }". I forgot to mention one other: o A function returning a bool could be implemented on some machines by setting the condition codes instead of storing a full integer value in the return register. Karl W. Z. Heuer (ihnp4!bentley!kwh), The Walking Lint
ark@alice.UucP (Andrew Koenig) (05/05/86)
>>Btw, you can't have *all* operators extended with "=". How would you write >>"v = v < e;"? (Not that it's useful.) > I think it's useful! As written, of course, it's semantically invalid, > but what you really mean is "v <= e" (sic) or, to demonstrate where it's > really useful, > array[horrendous] [subscript] [list] <= bigexpr; > rather than > if (array[h][s][l] < bigexpr) array[h][s][l] = bigexpr; > Now "<=" already means something else so this syntax is not acceptable. > How about "v < = e" with a mandatory blank? This is atrocious human > engineering but at least is parseable. Anybody have any better ideas? You have suggested that v < = e should mean if (v < e) v = e but this is not parallel to the other `=' operators. Instead, if it means anything at all it should mean v = v < e In other words, afterwards v is either 1 or 0 depending on the value of e and the previous value of v. But I can't imagine when I'd ever want to use this in practice. Maybe we should just leave the language alone.
ggs@ulysses.UUCP (Griff Smith) (05/06/86)
> In article <778@bentley.UUCP> kwh@bentley.UUCP (KW Heuer) writes: > >Btw, you can't have *all* operators extended with "=". How would you write > >"v = v < e;"? (Not that it's useful.) > I think it's useful! ... ... [ deleted usual arguments for "op-assign" operators ] > James F. Carter (213) 206-1306 > UCLA-SEASnet; 2567 Boelter Hall; 405 Hilgard Ave.; Los Angeles, CA 90024 > UUCP:...!{ihnp4,ucbvax,{hao!cepu}}!ucla-cs!jimc ARPA:jimc@locus.UCLA.EDU I think the quality of suggestions is degenerating rapidly. This is a blatant type clash. The "op-assign" interpretation of " <= " is self-contradictory nonsense. The expression "v < e" has the (nonexistent) type "boolean", which implies that the destination is also boolean. But that implies that you are using a boolean variable in the " < " relation, which would be nonsense if "bool" were a real type. Instead of proposing yet another obfuscation of the language, why don't we discuss ways that we can simplify and improve the clarity of our coding style within the confines of the current language. Better yet; quit talking, and do something about it. -- Griff Smith AT&T (Bell Laboratories), Murray Hill Phone: (201) 582-7736 Internet: ggs@ulysses.uucp UUCP: ulysses!ggs ( {allegra|ihnp4}!ulysses!ggs )
levy@ttrdc.UUCP (Daniel R. Levy) (05/06/86)
In article <12329@ucla-cs.ARPA>, jimc@ucla-cs.ARPA (Jim Carter) writes: >I think it's useful! As written, of course, it's semantically invalid, >but what you really mean is "v <= e" (sic) or, to demonstrate where it's >really useful, > array[horrendous] [subscript] [list] <= bigexpr; > rather than > if (array[h][s][l] < bigexpr) array[h][s][l] = bigexpr; >Now "<=" already means something else so this syntax is not acceptable. >How about "v < = e" with a mandatory blank? This is atrocious human >engineering but at least is parseable. Anybody have any better ideas? >-- >James F. Carter (213) 206-1306 >UCLA-SEASnet; 2567 Boelter Hall; 405 Hilgard Ave.; Los Angeles, CA 90024 >UUCP:...!{ihnp4,ucbvax,{hao!cepu}}!ucla-cs!jimc ARPA:jimc@locus.UCLA.EDU First, one could use the preprocessor to help: #define UPMAX(i,j) if ((i) < (j)) (i) = (j) ... UPMAX(array[h][s][l],bigexpr); While the output of cpp would look real messy, comp would handle this just fine. Of course, you lose (as with any macro which uses an argument more than once) if the arguments have side effects such as ++ (but that isn't the case here, right?). Or if you know that the optimizer is not smart enough to catch this and will evaluate the entire array[h][s][l] including subscripts twice (as well as bigexpr), you can force temp variables: FOO array[I][J][K]; ... FOO *atmp; FOO btmp; ... atmp = &(array[h][s][l]); btmp = bigexpr; UPMAX(*atmp,btmp); As for the lousy human engineering in requiring extra blanks in certain expressions, don't we have that already in C, e.g.: a = b/*c; /* did this mean divide b by *c, or to start a comment? */ ; a=*b; /* compiler complains about "ambiguous assignment" here */ -- ------------------------------- Disclaimer: The views contained herein are | dan levy | yvel nad | my own and are not at all those of my em- | an engihacker @ | ployer or the administrator of any computer | at&t computer systems division | upon which I may hack. | skokie, illinois | -------------------------------- Path: ..!{akgua,homxb,ihnp4,ltuxa,mvuxa, vax135}!ttrdc!levy
kwh@bentley.UUCP (KW Heuer) (05/06/86)
In article <12329@ucla-cs.ARPA> jimc@ucla-cs.ARPA (Jim Carter) writes: >In article <778@bentley.UUCP> kwh@bentley.UUCP (KW Heuer) writes: >>Btw, you can't have *all* operators extended with "=". How would you write >>"v = v < e;"? (Not that it's useful.) > >I think it's useful! As written, of course, it's semantically invalid, Whoa! The operator I was referring to was "v = v < e", which is the clear generalization of "op=" on operator "<". This is meaningful in C, because the boolean result of "<" will be interpreted as an integer. But it is not generally useful, because one does not normally use a boolean argument to a comparison operator like "<". >but what you really mean is "v <= e" (sic) or, to demonstrate where it's >really useful, > array[horrendous] [subscript] [list] <= bigexpr; > rather than > if (array[h][s][l] < bigexpr) array[h][s][l] = bigexpr; Now we're discussing "if (v < e) v = e;" which means "v = max(v,e);". This is indeed a useful operation, but the operator is now "max" rather than "<". >Now "<=" already means something else so this syntax is not acceptable. >How about "v < = e" with a mandatory blank? This is atrocious human >engineering but at least is parseable. Anybody have any better ideas? Yes. I already mentioned this in the discussion about builtins, but I think it bears repeating. Introduce a new operator "<>" for max (and "><" for min). Add the corresponding assignment operator "<>=" (and "><=") with the above meaning. The symbol "<>" is currently meaningless in C, though basic and pascal users would have a fit. "|>" and "<|" may be better choices. "\/" and "/\" would mimic the mathematical notation, but there may be reasons to avoid the use of backslash in program source. Karl W. Z. Heuer (ihnp4!bentley!kwh), The Walking Lint
rbj@icst-cmr (Root Boy Jim) (05/06/86)
> > In article <778@bentley.UUCP> kwh@bentley.UUCP (KW Heuer) writes: > > >Btw, you can't have *all* operators extended with "=". How would you write > > >"v = v < e;"? (Not that it's useful.) > > I think it's useful! ... > ... [ deleted usual arguments for "op-assign" operators ] > > James F. Carter (213) 206-1306 > > UCLA-SEASnet; 2567 Boelter Hall; 405 Hilgard Ave.; Los Angeles, CA 90024 > > UUCP:...!{ihnp4,ucbvax,{hao!cepu}}!ucla-cs!jimc ARPA:jimc@locus.UCLA.EDU > > I think the quality of suggestions is degenerating rapidly. This is a > blatant type clash. The "op-assign" interpretation of " <= " is > self-contradictory nonsense. The expression "v < e" has the > (nonexistent) type "boolean", which implies that the destination is > also boolean. But that implies that you are using a boolean variable > in the " < " relation, which would be nonsense if "bool" were a real type. It would be nonsense IF boolean was a real type. There is no need to make any distinction between them. It just gets in the way of coding. APL, the most mathematical language, treats booleans exactly like C. THERE IS NO SUCH THING AS A BOOLEAN DATA TYPE (to which Doug Gwyn will reply `there is no such thing as an integer either :-). There may be boolean OPERATORS, but their range and domain is integers. > Instead of proposing yet another obfuscation of the language, why don't > we discuss ways that we can simplify and improve the clarity of our > coding style within the confines of the current language. Better yet; > quit talking, and do something about it. Like what? Make it like Pascal :-) > Griff Smith AT&T (Bell Laboratories), Murray Hill > Phone: (201) 582-7736 > Internet: ggs@ulysses.uucp > UUCP: ulysses!ggs ( {allegra|ihnp4}!ulysses!ggs ) A couple of wild suggestions myself. In the tradition of APL one liners, 1) Chain Lvalues. I would like to be able to write: ((n *= 10) += (c -= '0'); instead of c -= '0'; n *= 10; n += c; 2) More of the same. We all know about *++p. But what if I want to jump more than one element? I can't write *(p += 2); Or maybe I want to write `p = &(i += 5). 3) Exchange operator. This has probably been discussed before, so pardon me if I blunder into that pit. BUT, DMR has stated that one of the reasons that exponentiation was left out was because no (or few, if any) machine could do it inline, and therefore all the compiler would be doing is a function call anyway. By the same reasoning, exchange CAN be done efficiently by some machines, and the hack of a temporary variable and three assignments is a rather stale idiom. The three statement XOR trick avoids the temporary, at the expense of execution time and clarity. 4) Allow complex statements to be considered as expressions so that the comma operator can be used to avoid braces, as in if (e) x = y, return z; 5) Allow immediate constants. Currently, there is only one special case, that of a character array. One can say char *p = "string"; and have the string squirreled away and the (magic) address stuffed into the pointer. Why not int *p = &5; where the integer five is whisked away and replaced by its address. Sure would eliminate a lot of housekeeping variables. 6) Eliminate arrays altogether! Well not exactly, but make all arrays vectored in all dimensions. This would show those quiche eaters what a real tough language C is :-). Array syntax would still be available of course, but would be translated into glorious pointer notation. And it wouldn't matter whether a variable was defined differently than it was declared (char x[] or char *x). 7) Negative Structure Offsets. After reading those last few, I don't expect anyone to take me seriously, but I am serious. These can be real useful for such things as communications, where each block is wrapped in another layer. We can even use the entry keyword for this (quick before ANSI takes it out :-). The advantage is real and twofold. First, all offsets are] known at compile time, and second, if the data is redone, only the code that uses it need be recompiled. This could be a win, especially if other programs used the same data. 8) Allow formal arguments to be declared AFTER the opening brace. This would allow prioritization of register variables. Well that should be enuf to chew on. I'm not really seriously suggesting munging the language. This is just a thought experiment in the art of the possible. I'm not even going to mention such radical changes as explicit end statements (gid rid of braces), an #include MACRO from FILE, or using backquotes as explicit substition characters (to allow concatenation of tokens, but it would break strings with backquotes in them, be them ever so few) as these would be major redefinitions. Now I will go on vacation until all the flames die out :-). (Root Boy) Jim Cottrell <rbj@cmr> "One man gathers what another man spills"
franka@mmintl.UUCP (Frank Adams) (05/06/86)
In article <12329@ucla-cs.ARPA> jimc@ucla-cs.UUCP (Jim Carter) writes: >I think it's useful! As written, of course, it's semantically invalid, >but what you really mean is "v <= e" (sic) or, to demonstrate where it's >really useful, > array[horrendous] [subscript] [list] <= bigexpr; > rather than > if (array[h][s][l] < bigexpr) array[h][s][l] = bigexpr; >Now "<=" already means something else so this syntax is not acceptable. >How about "v < = e" with a mandatory blank? This is atrocious human >engineering but at least is parseable. Anybody have any better ideas? What you talking about isn't "<=". It's "\/=" (to use a notation which showed up here recently). I.e., v = min(v,e), not v = v < e. The latter really is pretty useless. Frank Adams ihnp4!philabs!pwa-b!mmintl!franka Multimate International 52 Oakland Ave North E. Hartford, CT 06108
ado@elsie.UUCP (Arthur David Olson) (05/07/86)
> The. . .header file that I mentioned a few days ago. . . > contains the following: > > typedef int bool; /* boolean data */ > #define false 0 > #define true 1 My recommendation to folks would be to use the defines that appear in the 4.?bsd version of "curses.h"-- # define TRUE (1) # define FALSE (0) --on a conditional basis in any "nifty_header.h" file, a la: #ifndef TRUE #define TRUE (1) #define FALSE (0) #endif Using the "unnecessary" parentheses that appear in "curses.h" will prevent any "redefined to a different value" diagnostics if you both #include "curses.h" and #include "nifty_header.h" while conditionalizing the definitions as above will prevent "redefined (though not to a different value)" diagnostics if you include both files in the order shown above. -- UUCP: ..decvax!seismo!elsie!ado ARPA: elsie!ado@seismo.ARPA DEC, VAX, Elsie & Ado are Digital, Borden & Shakespeare trademarks.
cudcv@daisy.warwick.UUCP (Rob McMahon) (05/07/86)
In article <412@brl-smoke.ARPA> gwyn@brl.ARPA writes: >typedef int bool; /* boolean data */ >#define false 0 >#define true 1 What about typedef enum { false, true } bool; ? -- UUCP: ...!mcvax!ukc!warwick!cudcv JANET: cudcv@uk.ac.warwick.daisy ARPA: cudcv@daisy.warwick.ac.uk PHONE: +44 204 523037 Rob McMahon, Computer Unit, Warwick University, Coventry CV4 7AL, England
sbs@valid.UUCP (Steven Brian McKechnie Sargent) (05/08/86)
This group has lately been besieged with a variety of odd C features, namely * boolean operators and data types * builtin functions * New operators like "< =" * Arguments passed in registers All these have the same effect of reducing simplicity for doubtful gain. ** A Boolean data type distinct from integers clutters the language with another (moderately useless) type and removes handy idioms like foo[x == 0] = bar; (Vide the "enum" type, which doesn't participate in address arithemtic either.) Arguments that boolean functions make for more efficient implementations are pretty puny: > o A function returning a bool could be implemented on some machines by > setting the condition codes instead of storing a full integer value in > the return register. If the caller wants to use the result of the function as a value, rather than as input to a branching decision, then it must write branches anyway to set the value appropriately. Result: bigger slower code. > >o Multiple flag variables with local scope and no address operator (e.g. > > variables declared "register bool") could be packed into a single word. Last I checked, (flags&BOOLEAN_VALUE_OF_MERIT) did what you want. Packing and unpacking don't come for free, in space or time. ** Builtin functions confuse language implementation with programming environment implementation; C lives in enough different environments that this is just plain bad planning. "Inline functions," a la those of C++, are another matter entirely (although they have been mentioned repeatedly in discussions of builtin functions). The benefits that inline functions offer over CPP macros are: simpler cleaner syntax, more flexibility because they admit arbitrary control structure within, and avoidance of horrible botches like putchar(*p++). The disadvantage, at least in my mind, is uncertainty as to what happens to the free variables of an inline function. Are they bound lexically where the inline is declared, or are they bound at the point where the inline is used, assuming the nearest enclosing scope? Consider: int oddval; // Not odd, as in = 1 (mod 2), but "odd" inline max(x, y) { ++oddval; return (x > y)? x: y; } foo(oddval) { int n = max(oddval, 0); oddval = max(4, oddval); return max(oddval, oddval); } bar(x) { ... return max(x, 4); } The question that leaps to mind is "what the hell does this code hope to achieve?" You can of course write just as silly code using the C preprocessor; but then the question becomes: Why provide redundant ways to write this unsafely? ** New operators like "< =", in addition to being hard to spell and understand, facilitate usages that just aren't that common. I hardly ever want to say x = (x < y), and I don't mind typing the extra characters. I'm not interested in paying compiler vendors money for supporting this (or any other dubious misfeature pounded into the language for "completeness' sake.") ** There's also been a discussion about arguments passed in registers, with one fellow (sorry I forget the name) noting that "microcomputer people pass arguments in registers." Well, big computer people do the same thing, and in both cases the disease is one of not thinking through to the consequences of your actions. Suppose you pass arguments in registers. Well, if you're like me, you have a lot of variables in registers. So in order to pass your arguments, you have to save those registers somewhere. Where do you do it? Put them on the stack, of course. Well, suppose that you "know" that %3 and %4 are reserved for parameter passing: then those registers are unavailable to the caller, whose code gets correspondingly bigger and slower. Well, suppose you're keeping the arguments in %3 and %4, and the callee can use them "in place" because caller and callee have agreed to do that (in order to avoid the overhead of explicit parameter moving). Now, you're writing spaghetti code, full of "special" communication among routines, with all the attendant side effects and untraceable bugs. And why for? The speed gain from non-standard calling sequences seems marginal at best: one recent posting discussed at great length the most efficient way to present arguments to the UNIX open(2) call -- which executes hundreds or thousands of instructions inside namei, involving perhaps multiple waits for the disk in order to fetch the inode for the file! Put the arguments on a linked list of bit-wide elements and force the kernel to chase them down, if you want: it won't make much of a difference in how fast your programs run. ** It's lots of fun to talk about wonderful "features" we'd like to see, but somebody (ANSI?) might be listening and do something about it. So, for my $.02 worth: * Always strive to separate language from libraries, libraries from host environment, and host environment from development environment. These are all separate entities; make their interactions as clean as possible. * Keep implementations simple. This means: eschew oddball calling sequences that are hard for debuggers to follow. This means: minimize the number of compile-time options -- the user needs to determine the meaning of his program from the source code; don't confuse the process by throwing in options that invisibly change this meaning. * Be EXTREMELY conservative about adding features. I have yet to see a feature proposed that fixes a crippling problem of the language. Quite the opposite: many proposed features, such as unary + to denote evaluation ordering, help a min- ority of users while making the language more baroque for everybody. I do go on, don't I? Oh, well; enjoy, flame back, or whatever. Blessed be, S.
wendyt@pyramid.UUCP (Wendy Thrash) (05/08/86)
WARNING: This article discusses compiler issues, not specifically C language issues. In article <268@valid.UUCP> sbs@valid.UUCP (Steven Brian McKechnie Sargent) writes: >* Arguments passed in registers... >... have the same effect of reducing simplicity for doubtful gain. I don't want to quote too much of the original article -- it was rather long. The thrust of it was that passing parameters in registers doesn't make things run faster. This does not fit with my experience. When we implemented parameter passing in registers at Zilog, it was a big win. The argument that register variables must be pushed on the stack in order to pass parameters in registers seems tenuous. If you have only one set of registers available for variables, you have to save them sometime, unless the routine you are calling has no register variables itself. More commonly, registers used for parameter passing are not used for register variables; they may be used for temporaries. It is true that this may cut down on the number of available registers, but our work showed that we had enough registers remaining to allow good code generation for most programs. We did, indeed, allow the callee to use its arguments in place. Mr. Sargent's statements about "spaghetti code" make no sense at all to me -- this was a COMPILER; it was designed to produce efficient assembly language, not readable assembly language. When the compiler functioned correctly (as it usually did) there were no "attendant side effects and untraceable bugs." I will admit that this parameter passing caused difficulties. In particular, varargs code was messy, and debuggers more difficult to implement. Was it worth it? I believe so. Our emphasis was on speed, and that we had. Of course, this is all moot on RISC machines with sliding register windows. The concept of parameter passing in registers is then wired into the architecture, and there are plenty of registers left for register variables. --- Disclaimer: My opinions have obviously been influenced by the parameter passing in registers of my former employer (Zilog) and the sliding windows of my current employer (Pyramid). -- Wendy Thrash {allegra,cmcl2,decwrl,hplabs,topaz,ut-sally}!pyramid!wendyt Pyramid Technology Corp, Mountain View, CA +1 415 965 7200 ext. 3001
throopw@dg_rtp.UUCP (Wayne Throop) (05/08/86)
> jimc@ucla-cs.ARPA (Jim Carter) >> kwh@bentley.UUCP (KW Heuer) >>Btw, you can't have *all* operators extended with "=". How would you write >>"v = v < e;"? (Not that it's useful.) > I think it's useful! As written, of course, it's semantically invalid, > but what you really mean is "v <= e" (sic) or, to demonstrate where it's > really useful, > array[horrendous] [subscript] [list] <= bigexpr; > rather than > if (array[h][s][l] < bigexpr) array[h][s][l] = bigexpr; The point is not that it isn't useful to collapse multiple array (or other clumsy) references. The point is that in "e1 = e1 < e2", the "<" operator assumes arguments with numeric semantics and yeilds a value with boolean semantics. Since e1 is both an argument and a result, this expression isn't very meaningful. The fact that C overloads the numeric types with boolean meaning doesn't make this a useful thing to do. Interestingly, if e2 also has boolean semantics, the "e1 < e2" gives the same result as "!e1 && e2" (ignoring side effects). Doesn't seem like a primitive to clammor for in the language, nor does "<" seem like a good symbol for it if it were a primitive. Now, I know what all you hackers are saying. You're saying "But Wayne, how did you become a LOVE GOD?" (What's that? net.lang.c? Not net.panting.singles? Sorry, I mean) "But Wayne, I just don't care diddly about numeric vs boolean type safety debates. I just want something that'll WORK." Ok. Fine. But you'll probably be looking for subtle and disgusting bugs in programs that contain oddities like "e1 = e1 < e2" long after others are happily using working programs that don't. So there. -- Wayne Throop <the-known-world>!mcnc!rti-sel!dg_rtp!throopw
rcd@nbires.UUCP (05/09/86)
> >Btw, you can't have *all* operators extended with "=". How would you write > >"v = v < e;"? (Not that it's useful.) A more precisely stated rule, for C, would be that you can extend any dyadic operator whose result type is the same as the type of the first operand, but... > I think it's useful! As written, of course, it's semantically invalid, > but what you really mean is "v <= e" (sic) or, to demonstrate where it's > really useful, > array[horrendous] [subscript] [list] <= bigexpr; > rather than > if (array[h][s][l] < bigexpr) array[h][s][l] = bigexpr; Cf. Icon, in which the success/failure of a conditional is separate from its value. Icon's <= operator (as all of its relational operators) yields the value of its right operand if it succeeds; otherwise it fails (meaning no result is produced). The semantics described above in ">" is just that of Icon's <:= operator. -- Dick Dunn {hao,ucbvax,allegra}!nbires!rcd (303)444-5710 x3086 ...Cerebus for dictator!
rbutterworth@watmath.UUCP (Ray Butterworth) (05/09/86)
> > lots of us say "typedef short bool" in our .h files. > typedef char bool; uses less space on some machines. And on some machines it uses more space. Some machines can reference an int with a single instruction, but checking the value of a byte might take several. The one I am using now does the "if(integer)" test in 4 bytes of machine instructions, but "if(character)" takes 12 bytes. So defining it as short or char instead of int might save you 1 or 3 bytes of storage, but it also might cost you several times this amount EVERY time you reference the variable. In general you should always use int (or long). short (or char) should only be used for structures read in from an external source or for large arrays where the saving in space for the data is significantly large. Of course if you aren't worried about portable efficiencies do whatever is best for your machine. On the other hand, I'd like to think that at least some of the software I write now will still be running in 10 years, but I have my doubts about whether or not some of the machines I am using now will still be here then. (I can think of some wonderful code I wrote for an IBM1620 not much more than 10 years ago.)
greg@utcsri.UUCP (Gregory Smith) (05/09/86)
In article <602@brl-smoke.ARPA> rbj@icst-cmr (Root Boy Jim) writes: >2) More of the same. We all know about *++p. But what if I want to jump > more than one element? I can't write *(p += 2); Or maybe I > want to write `p = &(i += 5). You can write *(p += 2). For *p++, you can write *((p += 2 ) - 2 ) if you really want to. If p is a register, there will be little penalty over dereferencing *before* the p+=2. Why you wanna do p = &(i += 5 ) ?????? Like your immortal `exit(1,fprintf(stderr,"Arrg!!\n"))' this is an artificial combination of two unconnected statements. What's wrong with `i+=5; p= &i'? ( You probably prefer i+=5,p= &i; ) > >3) Exchange operator. This has probably been discussed before, so pardon > me if I blunder into that pit. BUT, DMR has stated that one of > the reasons that exponentiation was left out was because no > (or few, if any) machine could do it inline, and therefore > all the compiler would be doing is a function call anyway. > By the same reasoning, exchange CAN be done efficiently by > some machines, and the hack of a temporary variable and > three assignments is a rather stale idiom. The three > statement XOR trick avoids the temporary, at the expense > of execution time and clarity. > Good stuff. Even machines without an EXG can use a scratch register, which is better than using a user-supplied temp. What, by the way, is the XOR trick? >4) Allow complex statements to be considered as expressions so that > the comma operator can be used to avoid braces, as in > > if (e) x = y, return z; > Errr... well.... I'm not a compiler guru, but.... In the current ( conventional ) setup, compilation of expressions is done separately from 'statement processing' ( i.e. returns, ifs, whiles, cases, etc ). Your suggestion would require that the two be entwined together, which would make generation of really good code a difficult thing. Currently, when an expression is found, a tree is built, then the tree is crunched upon, and the code is generated. If every statement was an expression, then expression trees would need to have nodes for ifs and whiles, etc... ( starting to get LISPy). This could of course get very messy, and a really good coder is already a fairly messy thing to do. Besides, I don't think this would help very much, except for Obfuscated C entries. >5) Allow immediate constants. Currently, there is only one special > case, that of a character array. One can say char *p = "string"; > and have the string squirreled away and the (magic) address > stuffed into the pointer. Why not int *p = &5; where the > integer five is whisked away and replaced by its address. > Sure would eliminate a lot of housekeeping variables. > Fine by me. I would also like to suggest struct constants/rvalues. Suppose I have struct foo{ int f1; char f2; char *bar; } foo_var; I'd like to write something like this ( an executable statement ): foo_var = struct foo{ /* set structure value */ .bar = "Ergo Sum"; .f1 = 73; .f2 = '?'; }; This allows the use of unnamed (structure constants). #define cmplx(a,b) struct complex { .r=(a); .i=(b); } #define J cmplx( 0.0,1.0 ) cvar1 = cmul( cvar2, cmplx( 2.0, 1.02 ) ); I think it is important that the member names be used instead of the order. Also, it would be nice if the compiler were smart in cases like xchar = struct foo{ .bar="??"; .f2 = ychar+1; .f1 = func(i); }.f2; not to generate all the code to compute f1 and bar ( Holy side-effects, Batman! ). The above line could arise by a macro expansion. I have though out many of the implementation details, and I *still* think it's a good idea :-). I am very open to suggestions about the syntax. I will ramble on about/ argue about this later if you want ( and probably if you don't want 8-) <- peril-sensitive sunglasses. ). >6) Eliminate arrays altogether! Well not exactly, but make all > arrays vectored in all dimensions. This would show > those quiche eaters what a real tough language C is :-). > Array syntax would still be available of course, but would > be translated into glorious pointer notation. And it wouldn't > matter whether a variable was defined differently than it > was declared (char x[] or char *x). > Fully vectored arrays were used in B, and I like C's stuff better. You can always set up vectored arrays if you want - and still say array[i][j][k] into the bargain. Of course, you have to set up the vectors yourself... > >8) Allow formal arguments to be declared AFTER the opening brace. > This would allow prioritization of register variables. > Well, register arguments need to copied from the stack anyway, so you can declare your own with an explicit copy. But it wouldn't hurt to let the compiler do it. Since it silly ( presently ) to say `foo(p){ register char *p;...' this could be taken as an argument declaration. I have a related suggestion. Suppose I have the following: f(){ ... { int x,y; ... } { double xy; ... } } I would expect x and y to share the same stack space with xy. Now look at this ( assume 4 regs available ): f(){ register i,j,k,l,m; /* more vars than regs available */ { register ii ..... }; } I think the inner loop should push 'l' ( the lowest priority reg var ) on the stack and keep 'ii' in that reg, since ii will probably get more use in the inner block. The register priority would become ii/i/j/k, so if a further nested block said 'register a,b', the next regs to be kicked out would be j and k, leaving the priority as a/b/ii/i. At the end of the block, the value of l would be popped. If the block were the body of a loop, the pushing/popping would need to be done outside the actual loop, for speed. Inside the loop, of course, 'l' would be addressed as an auto. This allows C programmers one more advantage previously available only to assembler programmers: the re-use of registers for completely different things. The problem is that it would make jumping into/out of blocks a mess. I guess the compiler would have to detect this and generate 'fix' code for the jumps. -- "Canabee be said2b or not2b anin tire b, if half thabee isnotabee, due2 somain chunt injury?" - Eric's Dilemma ---------------------------------------------------------------------- Greg Smith University of Toronto UUCP: ..utzoo!utcsri!greg
davidsen@steinmetz.UUCP (Davidsen) (05/09/86)
In article <210@sdchema.sdchem.UUCP> tps@sdchema.UUCP (Tom Stockfisch) writes: >In article <778@bentley.UUCP> kwh@bentley.UUCP writes: >>In article <838@ihwpt.UUCP> ihwpt!knudsen writes: >>>(2) There isn't any ^^ (XOR) operator either, as in >> >>There is, but it's spelled "!=". (Presumably more efficient than "^", though >>I think either one should work with a smart compiler.) >> > >Not quite the same. > 3 ^^ 4 >would evaluate as 0, > 3 != 4 >evaluates as 1. > >-- Tom Stockfisch, UCSD Chemistry XOR can be defined as an (ugly) macro, I believe. #define XOR(a,b) (((a) != 0) != ((b) != 0) /* or if you like small better than readable */ #define XOR(a,b) (!!(a) != !!(b)) -- -bill davidsen seismo!rochester!steinmetz!--\ / \ ihnp4! unirot ------------->---> crdos1!davidsen \ / chinet! ---------------------/ (davidsen@ge-crd.ARPA) "Stupidity, like virtue, is its own reward"
gwyn@BRL.ARPA (VLD/VMB) (05/09/86)
One can define "bool" to be a variety of things, including an enumeration type, but as C was designed the result of a relational expression (for example) is an int; that's what Boolean data in C really "is".
gwyn@BRL.ARPA (VLD/VMB) (05/09/86)
Steven Brian McKechnie Sargent <valid!sbs> says ("> ..."): > A Boolean data type distinct from integers clutters the language with > another (moderately useless) type and removes handy idioms like > foo[x == 0] = bar; Boolean quantities form an important abstract data type distinct from counters, sets, real numbers, etc. By not making the distinction, the language encourages usage errors, the most notorious being if ( a = b ) stuff; Sure, one can make integers do double (or triple, or ...) duty, but by now every programmer should realize the value of data abstraction. > New operators like "< =", in addition to being hard to spell and understand, > facilitate usages that just aren't that common. I hardly ever want to > say x = (x < y), and I don't mind typing the extra characters. I'm not > interested in paying compiler vendors money for supporting this (or any > other dubious misfeature pounded into the language for "completeness' > sake.") Here is an example where proper use of Boolean data would be violated. A statement like x = x < y; should NEVER be used, since it assigns a Boolean result to an arithmetic variable. This means that a "< =" operator is not a good idea. I find data abstraction to be a Good Thing, and have produced much better code since defining a Boolean data type and using it in a strictly type-correct manner.
peter@baylor.UUCP (05/10/86)
> Not quite the same. > 3 ^^ 4 > would evaluate as 0, > 3 != 4 > evaluates as 1. Wrong. Remember: 3 && 4 = 1 3 & 4 = 0 ^^ was intended by the original poster as a logical operator, not a boolean one (despite the title of the message). -- -- Peter da Silva -- UUCP: ...!shell!{baylor,graffiti}!peter; MCI: PDASILVA; CIS: 70216,1076
levy@ttrdc.UUCP (Daniel R. Levy) (05/12/86)
In article <732@steinmetz.UUCP>, davidsen@steinmetz.UUCP (Davidsen) writes: >XOR can be defined as an (ugly) macro, I believe. > >#define XOR(a,b) (((a) != 0) != ((b) != 0) >/* or if you like small better than readable */ >#define XOR(a,b) (!!(a) != !!(b)) >-- > -bill davidsen or even #define XOR(a,b) (!(a) != !(b)) since XOR(not-a,not-b) == XOR(a,b) -- ------------------------------- Disclaimer: The views contained herein are | dan levy | yvel nad | my own and are not at all those of my em- | an engihacker @ | ployer or the administrator of any computer | at&t computer systems division | upon which I may hack. | skokie, illinois | -------------------------------- Path: ..!{akgua,homxb,ihnp4,ltuxa,mvuxa, vax135}!ttrdc!levy
grr@cbmvax.cbm.UUCP (George Robbins) (05/12/86)
In article <357@pyramid.UUCP> wendyt@pyramid.UUCP (Wendy Thrash) writes: [...] >I don't want to quote too much of the original article -- it was rather long. >The thrust of it was that passing parameters in registers doesn't make things >run faster. This does not fit with my experience. When we implemented >parameter passing in registers at Zilog, it was a big win. *WAS* a big win - meaning maybe it looked good on benchmarks... [...] >I will admit that this parameter passing caused difficulties. In particular, >varargs code was messy, and debuggers more difficult to implement. Was it >worth it? I believe so. Our emphasis was on speed, and that we had. 1) pdp-11 style varargs was broken - no way from C to get a those arguments that got crammed into registers. 2) Because of the register assignment scheme used, you couldn't even blindly pass a list of variable arguments to a routine like printf that did know how to deal with them. 3) setjmp/longjmp got broken with respect to restoring register variable parameters somewhere along the way. In the long run, portability seems to have become the more important issue: Just try porting some of the code in mod.sources and net.sources to the machine and see how far you can get without having to go into the editor and start whacking at source code. Assume that software developers will have the same problems porting their wares... Also, note that Zilog has never delivered its ATT SVID blessed System V port, and that their next series of machines will contain ATT chips running vanilla 3Bx software... -- George Robbins - now working with, uucp: {ihnp4|seismo|caip}!cbmvax!grr but no way officially representing arpa: cbmvax!grr@seismo.css.GOV Commodore, Engineering Department fone: 215-431-9255 (only by moonlite)
hutch@sdcsvax.UUCP (Jim Hutchison) (05/12/86)
() well now for ||= you can use |= because C defines 0 as false and non-0 as true (Yes, I know that boolean expressions are defined to return 0/1 as defined in K&R if that is still used). typedef char bool; #define B_TRUE ((bool)1) #define B_FALSE ((bool)0) bool a, b; a = B_TRUE; b = (x == READY); ... b |= (x == READY); b ^= a; Now this can get you into trouble, because 2 and 1 and 47 are also "true". This is o.k. for '|' but not '^'. You could of course do b = (b == 0) ^ (a == 0) but that looks a bit strained. -- /* Jim Hutchison UUCP: {dcdwest,ucbvax}!sdcsvax!hutch ARPA: Hutch@sdcsvax.ucsd.edu [ Disclaimer eaten by a passing kiwi ] */
rbj@icst-cmr (Root Boy Jim) (05/14/86)
Doug Gwyn responds: Steven Brian McKechnie Sargent <valid!sbs> says ("> ..."): > A Boolean data type distinct from integers clutters the language with > another (moderately useless) type and removes handy idioms like > foo[x == 0] = bar; Boolean quantities form an important abstract data type distinct from counters, sets, real numbers, etc. By not making the distinction, the language encourages usage errors, the most notorious being if ( a = b ) stuff; True. It is easily found tho. Sure, one can make integers do double (or triple, or ...) duty, but by now every programmer should realize the value of data abstraction. Or lack of it. I find that the Boolean/Integer schism in Fortran caused me lots of headaches long ago. > New operators like "< =", in addition to being hard to spell and > understand, > facilitate usages that just aren't that common. I hardly ever want to > say x = (x < y), and I don't mind typing the extra characters. I'm not > interested in paying compiler vendors money for supporting this > (or any other dubious misfeature pounded into the language for > "completeness'sake.") Here is an example where proper use of Boolean data would be violated. A statement like x = x < y; should NEVER be used, since it assigns a Boolean result to an arithmetic variable. This means that a "< =" operator is not a good idea. Wrong you are, Doug. You have been thinking in this Boolean paradigm for so long that you are missing another Good thing. Implication! Given that P and Q are `Boolean' variables (0 or 1), the Logical Implication is described by the operator `<='. Thus, the statement `x = p <= q;' sets the `boolean' value x to a `boolean' expression. Since there are no such things as booleans :-), x, p, & q are integers. It's all a matter of interpretation. APL has no `boolean exclusive or' operator because the operator `!=' does the same thing (when given only zero's or one's). There are sixteen different boolean functions with two inputs and one output. They all fit nicely into C operators: p 0 0 1 1 q 0 1 0 1 Name Symbol --------- ---- ------ 0 0 0 0 False 0 0 0 0 1 And & 0 0 1 0 Doesn't Imply > 0 0 1 1 Alpha p 0 1 0 0 Not Implied By < 0 1 0 1 Omega q 0 1 1 0 Diff != or ^ 0 1 1 1 Or | 1 0 0 0 Nor !(p | q) 1 0 0 1 Same == 1 0 1 0 Not Omega !q 1 0 1 1 Is Implied By >= 1 1 0 0 Not Alpha !p 1 1 0 1 Implies <= 1 1 1 0 Nand !(p & q) 1 1 1 1 True 1 Neat! I never thought I'd get to use my engineering switching theory again! I find data abstraction to be a Good Thing, and have produced much better code since defining a Boolean data type and using it in a strictly type-correct manner. This fact doesn't bother people who write in APL, widely considered to be the most mathematical language. Why does it bother you? (Root Boy) Jim Cottrell <rbj@cmr> "One man gathers what another man spills"
kwh@bentley.UUCP (KW Heuer) (05/14/86)
In article <268@valid.UUCP> valid!sbs (Steven Brian McKechnie Sargent) writes: >A Boolean data type distinct from integers clutters the language I disagree. I think an explicit boolean datatype *simplifies* the language. The way I see it, booleans already exist internally. >and removes handy idioms like > foo[x == 0] = bar; I'd guess that would still be legal, just like "float x = 0;". The compiler could know how to convert bool to int. At worst, you could write "(int)" to force it. (I prefer to write "foo[x==0 ? 1 : 0] = bar;", which is no less efficient since that's how the compiler converts the "internal bool" into an int anyway.) >(Vide the "enum" type, which doesn't participate in address arithemtic >either.) I'd like to see a syntax to declare an array which is subscripted by an enum instead of an int. Having to use a cast is a pain. (In the example above, you didn't mean to imply that foo[] would only be indexed by bool, did you? If so, cancel my comment about "?:".) >Arguments that boolean functions make for more efficient implementations >are pretty puny: >> o A function returning a bool could be implemented on some machines by >> setting the condition codes instead of storing a full integer value in >> the return register. >If the caller wants to use the result of the function as a value, rather >than as input to a branching decision, then it must write branches anyway >to set the value appropriately. Result: bigger slower code. No slower than putting the same branch in the called function! Anyway, I suspect that most boolean functions *are* used in a boolean context rather than an integer context. >> >o Multiple flag variables with local scope and no address operator (e.g. >> > variables declared "register bool") could be packed into a single word. >Last I checked, (flags&BOOLEAN_VALUE_OF_MERIT) did what you want. Packing >and unpacking don't come for free, in space or time. "Packing and unpacking" don't need to be done except in an integer context. The boolean operations are single instructions. As for (f&CONST), I'd just like to reduce the ugliness. Cf. bitfields. >** >Builtin functions confuse language implementation with programming >environment implementation; C lives in enough different environments >that this is just plain bad planning. "Inline functions," a la those >of C++, are another matter entirely (although they have been mentioned >repeatedly in discussions of builtin functions). The benefits that >inline functions offer over CPP macros are: simpler cleaner syntax, >more flexibility because they admit arbitrary control structure within, >and avoidance of horrible botches like putchar(*p++). The disadvantage, >at least in my mind, is uncertainty as to what happens to the free >variables of an inline function. Are they bound lexically where the >inline is declared, or are they bound at the point where the inline is >used, assuming the nearest enclosing scope? Consider: [example deleted] I think I agree about builtins. There's no problem with "putchar(*p++)", I believe you're thinking of "putc(c, *fp++)". It's my understanding that "inline" has the same semantics as "static", but is a hint to the compiler; your example may force the compiler to forgo the inline expansion. >** >New operators like "< =" ... I originally mentioned this just to point out that there exist operators which cannot be extended with "op=". The one person who thought it would be useful was confusing it with "MAX=". (Mark Brader has pointed out that B, a sibling* language to C, actually has these operators (spelled "=<", etc.) for completeness. I still think they're useless.) >** >... I have yet to see a feature proposed that fixes a crippling problem of >the language. Do you know of any "crippling problems" that require new features? Anyway, it's useful to keep in mind that much of what is said here (by me, certainly) is not a "proposal", but just an idea to be tossed around in the think tank. As an example of such, here's an idea which I do *not* want to see in the next ANSI draft. In stepping through a linked list (recursive structure), one often writes "p=p->next;". The logic that creates "+=" would suggest that this could be written "p->=next". However, "->" is not really an operator since its right "argument" is not an expression. An alternate notation would be "p=>next", where "=>" is a sort of overstrike between "->" and "=". (I actually had a case once where this would've been useful -- "p" was an expression with side effects!) Karl W. Z. Heuer (ihnp4!bentley!kwh), The Walking Lint *The original B was a parent language of C; modern B is a sibling.
gwyn@BRL.ARPA (VLD/VMB) (05/14/86)
Index to participants: >>> Steven Brian McKechnie Sargent >> Doug Gwyn > Jim Cottrell >>> New operators like "< =", in addition to being hard to spell and >>> understand, >>> facilitate usages that just aren't that common. I hardly ever want to >>> say x = (x < y), and I don't mind typing the extra characters. I'm not >>> interested in paying compiler vendors money for supporting this >>> (or any other dubious misfeature pounded into the language for >>> "completeness'sake.") >> >> Here is an example where proper use of Boolean data would be violated. >> A statement like >> x = x < y; >> should NEVER be used, since it assigns a Boolean result to an >> arithmetic variable. This means that a "< =" operator is not >> a good idea. > > Wrong you are, Doug. You have been thinking in this Boolean paradigm > for so long that you are missing another Good thing. Implication! > Given that P and Q are `Boolean' variables (0 or 1), the Logical > Implication is described by the operator `<='. Thus, the statement > `x = p <= q;' sets the `boolean' value x to a `boolean' expression. > Since there are no such things as booleans :-), x, p, & q are integers. > It's all a matter of interpretation. APL has no `boolean exclusive or' > operator because the operator `!=' does the same thing (when given > only zero's or one's). There are sixteen different boolean functions > with two inputs and one output. They all fit nicely into C operators: > [table omitted] Even Boole knew that Boolean operations can be performed by appropriate arithmetic on {0,1} operands; that is irrelevant. The original example, x "< =" y;, interpreted as you suggest, would mean `set x to "x is not implied by y"', if and only if x and y were Boolean in the first place. Not only is this of negligible practical value, but that meaning of the operator differs from its meaning when applied to non-Boolean values (the general case, and the one I had in mind when I argued that it was a bad idea). >> I find data abstraction to be a Good Thing, and have produced >> much better code since defining a Boolean data type and using >> it in a strictly type-correct manner. > > This fact doesn't bother people who write in APL, widely considered > to be the most mathematical language. APL doesn't offer real facilities for data abstraction. > Why does it bother you? Because as a conscientious software engineer I have to produce reliable and maintainable systems for people to use. This requires quality standards well beyond what hackers might feel to be necessary.
mesans@uvicctr.UUCP (mesans) (05/14/86)
>>Not quite the same. >> 3 ^^ 4 >>would evaluate as 0, >> 3 != 4 >>evaluates as 1. > >If the left and right hand sides are both already boolean, `!=' works; >but the following macro always works: > > /* logical exclusive or */ > #define lxor(a, b) (((a) != 0) != ((b) != 0)) Which is equivalent to : !a != !b which I think you will agree is much simpler, and easyer to understand (at least I think so). S. John Banner
rbj@icst-cmr (Root Boy Jim) (05/15/86)
XOR can be defined as an (ugly) macro, I believe. #define XOR(a,b) (((a) != 0) != ((b) != 0) /* or if you like small better than readable */ #define XOR(a,b) (!!(a) != !!(b)) -- -bill davidsen /* smaller still */ #define XOR(a,b) (!!(a) == !(b)) (Root Boy) Jim Cottrell <rbj@cmr> "One man gathers what another man spills"
mnl@cernvax.UUCP (mnl) (05/16/86)
In article <2741@utcsri.UUCP> greg@utcsri.UUCP (Gregory Smith) writes: >In article <602@brl-smoke.ARPA> rbj@icst-cmr (Root Boy Jim) writes: > >>3) Exchange operator. This has probably been discussed before, so pardon >> me if I blunder into that pit. BUT, DMR has stated that one of >> the reasons that exponentiation was left out was because no >> (or few, if any) machine could do it inline, and therefore >> all the compiler would be doing is a function call anyway. >> By the same reasoning, exchange CAN be done efficiently by >> some machines, and the hack of a temporary variable and >> three assignments is a rather stale idiom. The three >> statement XOR trick avoids the temporary, at the expense >> of execution time and clarity. >> >Good stuff. Even machines without an EXG can use a scratch register, which >is better than using a user-supplied temp. >What, by the way, is the XOR trick? > To swap the contents of A and B (no particular language): A = A XOR B B = A XOR B A = A XOR B On some machines, assuming A and B are in registers, this won't take any more time than the normal three assignments using a temporary. -- Mark Nelson mnl@cernvax.bitnet or ...!seismo!mcvax!cernvax!mnl If the ACM had a sub-group for naturalists, would it be ACM SIGnature?
kwh@bentley.UUCP (KW Heuer) (05/16/86)
In article <1776@sdcsvax.UUCP> hutch@sdcsvax.UUCP writes: >well now for ||= you can use |= ... I think the intent was that "v ||= e" would not evaluate e if v were already true. (Same as "v = v || e".)
franka@mmintl.UUCP (Frank Adams) (05/17/86)
In article <147@daisy.warwick.UUCP> cudcv@daisy.warwick.ac.uk (Rob McMahon) writes: >In article <412@brl-smoke.ARPA> gwyn@brl.ARPA writes: >>typedef int bool; /* boolean data */ >>#define false 0 >>#define true 1 > >What about > typedef enum { false, true } bool; >? I will start using this when I can rely on having an ANSI standard compiler. At the moment, there are too many compilers where the expression in an if statement can't be an enum. (Not to mention compilers which don't support enums.) Frank Adams ihnp4!philabs!pwa-b!mmintl!franka Multimate International 52 Oakland Ave North E. Hartford, CT 06108
franka@mmintl.UUCP (Frank Adams) (05/17/86)
In article <2496@watmath.UUCP> rbutterworth@watmath.UUCP writes: >> > lots of us say "typedef short bool" in our .h files. >> typedef char bool; uses less space on some machines. > >And on some machines it uses more space. Which is why you put it in a .h file, instead of in each program separately. That way it can fairly easily be changed when you port. Frank Adams ihnp4!philabs!pwa-b!mmintl!franka Multimate International 52 Oakland Ave North E. Hartford, CT 06108
kwh@bentley.UUCP (KW Heuer) (05/17/86)
In article <814@bentley.UUCP> I wrote: >*The original B was a parent language of C; modern B is a sibling. I stand corrected. The features I described were part of "old" B.
aglew@ccvaxa.UUCP (05/22/86)
~> Boolean data type in C I say `typedef unsigned char bool'... Instead of using macros like lxor, I do #define boolval(bv) ((bv)!=0) so I can get away with saying boolval(XXX) ^ boolval(YYY) and the like. Doesn't help with waning to be able to do BBBBB &&= CCCCC; "Equal rights for Booleans!" has been my cry for a while - but I meant it with respect to computer architectures, not C. After all, C can't be expected to be better than present day architectures - C is just structured assembly language. :-). On second though, :-(. Andy "Krazy" Glew. Gould CSD-Urbana. USEnet: ihnp4!uiucdcs!ccvaxa!aglew 1101 E. University, Urbana, IL 61801 ARPAnet: aglew@gswd-vms
franka@mmintl.UUCP (Frank Adams) (05/26/86)
In article <822@brl-smoke.ARPA> rbj%icst-cmr@smoke.UUCP writes: > I find data abstraction to be a Good Thing, and have produced > much better code since defining a Boolean data type and using > it in a strictly type-correct manner. > >This fact doesn't bother people who write in APL, widely considered >to be the most mathematical language. Why does it bother you? When I was writing in APL, I found that a necessary part of writing good code was always knowing what the data I was dealing with was. (This doesn't mean that one cannot write a function which works for more than one data type; just that one must explicitly know that that is what one is writing.) If I wrote AxB, I knew whether A was a Boolean or a number; the ability to declare it could only have helped. The fact that one can map Booleans into numbers, and thereby get a number of Boolean operators from the arithmetic ones, is one of those great mixed blessings. There is a real loss in readability when one takes advantage of such things, as C and APL both do. I think Pascal and ADA are closer to the mark here, regarding Boolean as an instance of an enumeration type. This is not merely clever; it is correct. Frank Adams ihnp4!philabs!pwa-b!mmintl!franka Multimate International 52 Oakland Ave North E. Hartford, CT 06108
mike@peregrine.UUCP (Mike Wexler) (05/28/86)
In article <822@brl-smoke.ARPA> rbj@icst-cmr (Root Boy Jim) writes: > Boolean quantities form an important abstract data type distinct from > counters, sets, real numbers, etc. By not making the distinction, > the language encourages usage errors, the most notorious being > if ( a = b ) > stuff; > >True. It is easily found tho. ------ How do I easily find these? Given the following pseudocode fragment int xyz(parameter1,parameter2) { ... if (big_expression_1=big_expression_2) statement; ... } Where the "=" should be a "==" and the function is producing unexpected results how would you easily track down this failure. By easily I mean more easily than compiling the program and noticing the error about using an arithmetic expression where a boolean one was supposed to be. If this isn't what you meant by easily, what did you mean? -- Mike Wexler Email address:(trwrb|scgvaxd)!felix!peregrine!mike Tel Co. address: (714)855-3923 ;-) Internet address: ucivax@ucbvax.BERKELY.EDU!ucivax%felix!mike@peregrine :-(