maart@cs.vu.nl (Maarten Litmaath) (06/24/88)
Hello, it's me again.
This time the question is: why hasn't C got a logical xor operator?
logical and: &&
logical or: ||
logical xor: ^^ <- fits nicely!
Of course the way to come around the deficiency is:
if (!(expr1) != !(expr2)) {
...
}
but this only works if !0 always evaluates to the same value (viz. 1), that is,
the optimizer is not allowed to f*ck around with the comparison.
!0 is indeed a constant, isn't it?
--
I'd rather live in Russia |Maarten Litmaath @ Free U Amsterdam:
than in South-Africa... |maart@cs.vu.nl, mcvax!botter!ark!maart
karl@haddock.ISC.COM (Karl Heuer) (06/25/88)
In article <1310@ark.cs.vu.nl> maart@cs.vu.nl (Maarten Litmaath) writes: >This time the question is: why hasn't C got a logical xor operator? Since you posted the question to comp.std.c, I'll interpret the question as "Why wasn't logical xor added to ANSI C?". The answer is that it isn't useful enough to be worth the change to the language. >Of course the way to come around the deficiency is: [ !x != !y ] >but this only works if !0 always evaluates to the same value (viz. 1), Which it is and always has been. Of course, if you're dealing with true boolean expressions (and I hold the opinion that nothing else should be handed to a logical operator), then either "x != y" or "x ^ y" will do. Karl W. Z. Heuer (ima!haddock!karl or karl@haddock.isc.com), The Walking Lint
jfh@rpp386.UUCP (John F. Haugh II) (06/26/88)
In article <1310@ark.cs.vu.nl> maart@cs.vu.nl (Maarten Litmaath) writes: >Of course the way to come around the deficiency is: > > if (!(expr1) != !(expr2)) { > ... > } > >but this only works if !0 always evaluates to the same value (viz. 1), that is, >the optimizer is not allowed to f*ck around with the comparison. >!0 is indeed a constant, isn't it? >-- >I'd rather live in Russia |Maarten Litmaath @ Free U Amsterdam: > than in South-Africa... |maart@cs.vu.nl, mcvax!botter!ark!maart [ hey, chris, here is topic #2 for your posting ] which, as this discussion went a few months ago, is exactly the case. the code you've writen above, modulo any blindness on my part, should work perfect as an exclusive-or function. remember, exclusive-or is the not-equivalant operator, it returns true when the two operands are not boolean equivalant. the implied comparision against zero is performed automagically in the case of || and &&. as far as the optimizer is concerned, it should still be able to perform any optimizations which would be allowed for any other boolean operators, except you can't short circuit != or == as you can && and ||. in particular, i believe (a == 0)^(b == 0) most likely can't be as well optimized as (a == 0)!=(b == 0). i can't prove this to be true, but i very well suspect it may be. - john. ps - your .signature is thought provoking. i can't decide whether i'd rather live in a large communist country which oppresses blacks or a small capitalist country which oppresses blacks. hard choice. -- John F. Haugh II +--------- Cute Chocolate Quote --------- HASA, Division "S" | "USENET should not be confused with UUCP: killer!rpp386!jfh | something that matters, like CHOCOLATE" DOMAIN: jfh@rpp386.uucp | -- with my apologizes
karl@haddock.ISC.COM (Karl Heuer) (06/28/88)
In article <3254@rpp386.UUCP> jfh@rpp386.UUCP (The Beach Bum) writes: >in particular, i believe (a == 0)^(b == 0) most likely can't be as well >optimized as (a == 0)!=(b == 0). Nonsense. "!=" and "^" produce the same result when both operands are normalized booleans; therefore a compiler which detects this situation is free to generate its favorite logical-xor construct for both. In practice, few if any compilers bother to do this. Karl W. Z. Heuer (ima!haddock!karl or karl@haddock.isc.com), The Walking Lint
chris@mimsy.UUCP (Chris Torek) (06/28/88)
>In article <3254@rpp386.UUCP> jfh@rpp386.UUCP (The Beach Bum) writes: >>in particular, i believe (a == 0)^(b == 0) most likely can't be as well >>optimized as (a == 0)!=(b == 0). In article <4772@haddock.ISC.COM> karl@haddock.ISC.COM (Karl Heuer) writes: >Nonsense. "!=" and "^" produce the same result when both operands are >normalized booleans; therefore a compiler which detects this situation is free >to generate its favorite logical-xor construct for both. In practice, few if >any compilers bother to do this. In fact, the 4BSD Vax PCC does nothing special about either one. For if ((a==0) != (b==0)) code; one gets code of the form test a branch if not 0 -+ r0 = 1 | +---branch | | r0 = 0 <---------+ +-> test b branch if not 0 -+ r1 = 1 | +---branch | | r1 = 0 <---------+ +-> compare* r0,r1 branch if equal -+ <code> | ... <------------+ The only difference for if ((a==0) ^ (b==0)) is that the `compare' (marked with `*') turns into an `xor'. For assignment statements, however, c = (a==0) != (b==0); /* or c = (a==0) ^ (b==0) */ the code remains the same up until the `*' above; from there it reads either compare r0,r1 branch if equal -+ r0 = 1 | +---branch | | r0 = 0 <---------+ +-> move r0,c or xor r0,r1 move result,c Hence in a dumb compiler (PCC) the logical operation is more efficient. A good `rule of thumb' is this: ------------------------------------------------------------- Logical operators are never slower than arithmetic operators. ------------------------------------------------------------- [are there any machines for which this is false?] Comparison of two arbitrary quantities (as by a dumb compiler above) is a subtraction, which is arithmetic, hence ^ either ties or wins. Incidentally, in the 4.3BSD-tahoe Vax compiler, neither if ((a == 0) != (b == 0)) nor if ((a == 0) ^ (b == 0)) produce the best code. The best logical exclusive or sequence for `if' statements comes from if (a ? !b : b) which generates only 7 instructions, of which at most 5 are executed. Part of this is from some tweaks Donn Seeley and I installed recently to improve the code generated for the getc() and putc() macros. -- In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163) Domain: chris@mimsy.umd.edu Path: uunet!mimsy!chris
maart@cs.vu.nl (Maarten Litmaath) (06/28/88)
In article <3254@rpp386.UUCP> jfh@rpp386.UUCP (The Beach Bum) writes: \ps - your .signature is thought provoking. i can't decide whether i'd \ rather live in a large communist country which oppresses blacks \ or a small capitalist country which oppresses blacks. hard choice. I CAN decide whether I'd rather live in a country in which maybe not all people get on equally well, but at least are equal for the law, or a country in which the law states there be an apartheid between black and white (very smart solution to prevent the black majority from regaining the power and wealth stolen from them)... Now about the topic in the subject line. Karl W. Z. Heuer writes: >"Why wasn't logical xor added to ANSI C?". The answer is that it isn't useful >enough to be worth the change to the language. Well, it's strange K&R didn't think of it in the first place (don't give me the story about shortcutting: that's no reason for not implementing ^^). Furthermore, it can be implemented WITHOUT breaking existing code, and (admittedly) sometimes one would wish for ^^; but then again: isn't Karl having problems himself to get \c accepted by ANSI? :-) ANSI committee: "Yes, it's kinda nice. Go back and do your homework properly! Come back to us if you've found something dubious, about which we can spend a week arguing!" >Of course, if you're dealing with true boolean expressions (and I hold the >opinion that nothing else should be handed to a logical operator), then either >"x != y" or "x ^ y" will do. Come on Karl, what's so terrible about the following common practice? if (some_pointer && ...) { ... } -- I'd rather live in Russia |Maarten Litmaath @ Free U Amsterdam: than in South-Africa... |maart@cs.vu.nl, mcvax!botter!ark!maart
karl@haddock.ISC.COM (Karl Heuer) (06/29/88)
Let's leave the political discussions in a different newsgroup, okay? In article <1312@ark.cs.vu.nl> maart@cs.vu.nl (Maarten Litmaath) writes: >Karl W. Z. Heuer writes: >>"Why wasn't logical xor added to ANSI C?". The answer is that it isn't >>useful enough to be worth the change to the language. > >Well, it's strange K&R didn't think of it in the first place... "Why didn't K&R make a logical xor operator?" is a different question. I'll be glad to take this up in comp.lang.c after I return from vacation. >Furthermore, it can be implemented WITHOUT breaking existing code, This (or a weakened form of it) is a necessary condition for ANSI acceptance, but it is not sufficient. >and (admittedly) sometimes one would wish for ^^; but then again: isn't Karl >having problems himself to get \c accepted by ANSI? :-) It's hard to get anything new accepted by X3J11. This is as it should be. Do you want this operator just for completeness, or do you think you'd actually use it a lot? I can only think of one routine I've ever written in which I've needed a logical xor, and since both operands were boolean I simply used "^". >>(and I hold the opinion that nothing else [but a normalized boolean] should >>be handed to a logical operator) > >Come on Karl, what's so terrible about the following common practice? > if (some_pointer && ...) { ... } Well, since you asked: The problem with it is that, by looking at this code fragment in isolation, it's not obvious that some_pointer is a pointer, rather than an integer, a character, a real, or a boolean. If you explicitly write if (p != NULL && i != 0 && c != '\0' && r != 0.0 && b) { ... } the reader has more information, which often makes the code more readable. As I said, this is my personal opinion; I certainly don't think that the language should be changed to enforce it. Karl W. Z. Heuer (ima!haddock!karl or karl@haddock.isc.com), The Walking Lint
smryan@garth.UUCP (Steven Ryan) (06/29/88)
The lack of a boolean exclusive-or is probably cultural. Xor is important for bit fiddling, but few predicates use it. An equivalence operator (even if it is just a negated xor), on the other hand is useful for boolean but not bits. >A good `rule of thumb' is this: > > ------------------------------------------------------------- > Logical operators are never slower than arithmetic operators. > ------------------------------------------------------------- > >[are there any machines for which this is false?] Depends how you implement booleans. On a pipelined machine, jumps kill you.
castillo@mit-amt.MEDIA.MIT.EDU (Brian C. Anderson) (06/29/88)
In article <1312@ark.cs.vu.nl> maart@cs.vu.nl (Maarten Litmaath) writes: >In article <3254@rpp386.UUCP> jfh@rpp386.UUCP (The Beach Bum) writes: >\ps - your .signature is thought provoking. i can't decide whether i'd >\ rather live in a large communist country which oppresses blacks >\ or a small capitalist country which oppresses blacks. hard choice. > >I CAN decide whether I'd rather live in a country in which maybe not all >people get on equally well, but at least are equal for the law, or a country >in which the law states there be an apartheid between black and white (very >smart solution to prevent the black majority from regaining the power and >wealth stolen from them)... "equal for the law"? Fat chance if you've got Jewish parents, or are a practicing Christian, or you fall into any number of unacceptable political/religious/ethnic catagories. One of the most unbelievable spectacles of the modern age is seeing people favorably compare the Soviet Union's human rights record with that of South Africa. At least in that country if you don't like the status quo you can emigrate without waiting 20 years for an exit visa. BTW, what does any of this have to do with C?
alex@dbase.UUCP (Bob Alexander) (07/02/88)
In article <833@garth.UUCP> smryan@garth.UUCP (Steven Ryan) writes: >The lack of a boolean exclusive-or is probably cultural. Xor is important >for bit fiddling, but few predicates use it. An equivalence operator (even >if it is just a negated xor), on the other hand is useful for boolean but >not bits. > I would guess that much of the reason for including || and && in C was to provide the advantage of their short-circuiting properties. Short-circuiting could not be done with ^^. I wouldn't mind having it around, for completeness, but I would probably rarely use it. Just for kicks, how about: #define logical(x) ((x) != 0) /* logical affirmation */ #define logicalxor(x,y) (logical(x) != logical(y)) /* logical xor */ #define logicaleq(x,y) (logical(x) == logical(y)) /* logical equivalence */ For as often as I would use them, this would suffice. I would probably use the first one the most. Disclaimer: I accept no liability for possible misuse of the word "affirmation". Furthermore, the above definitions might not work at all -- haven't tried 'em.
mmengel@cuuxb.ATT.COM (~XT4103000~Marc Mengel~C25~G25~6184~) (07/02/88)
>>Of course, if you're dealing with true boolean expressions (and I hold the >>opinion that nothing else should be handed to a logical operator), then >>either "x != y" or "x ^ y" will do. >Come on Karl, what's so terrible about the following common practice? > if (some_pointer && ...) { > ... > } Ah, but fortunately C gave us a cheap and easy way to convert to "Boolean" -- so "!!x ^ !!y" does pretty well. I think the short circuit evaluation is the real reason -- after all, you could short circuit evaluate "x & y" if x is 0, and "x | y" if x is ~0, but you *don't* because then you would have to use explicit temp variables to evaluate both sides of the bitwise operator. -- Marc Mengel attmail!mmengel {lll-crg|mtune|ihnp4}!cuuxb!mmengel
bill@proxftl.UUCP (T. William Wells) (07/03/88)
In article <1310@ark.cs.vu.nl>, maart@cs.vu.nl (Maarten Litmaath) writes: > Hello, it's me again. > This time the question is: why hasn't C got a logical xor operator? > > logical and: && > logical or: || > logical xor: ^^ <- fits nicely! > > Of course the way to come around the deficiency is: > > if (!(expr1) != !(expr2)) { > ... > } The main reason for not adding your logical xor operator is this: the other two operators imply sequencing of evaluation, the logical xor operator can't. A && B means evaluate A and if it is true, evaluate B. The result of the expression is true (1) if the last expression evaluated is nonzero. However, your xor operator requires that both operands be evaluated; this makes it a bad idea to create an operator analogous to the others. This is not meant to imply that the functionality of a logical xor is not useful, only that that syntax would be a bad idea. If I really needed this functionality, I would create a macro logxor(a,b), using the expression you specified. However, it is rarely the case that I need this for arbitrary arguments; normally, I do this with logical values and for these the regular xor (^) operator is sufficient.