darren@revcan.UUCP (Darren Morbey) (04/15/91)
I would like to thank everyone who submitted responses to my question: How can one simulate -- portably -- a ^^ operator similar to && and ||? Also can it be guaranteed to execute both its operands once and only once (O&OO)? I realize I should have been more specific about what I said and what I knew (for example, && and || are, by definition, short-circuit, whereas ^^ could not be defined to do so.) I did take a look at K&R I from the Ottawa Public Library, so I understand more than I did when I asked. Preliminary note: Many of the responses involved "boolean normalization," i.e. converting a numeric value to (int) 0 for any zero value and (int) 1 for any non-zero value. (the casts are for clarity.) There were essentially two different ways of doing this in the responses, and one could always be substituted for the other. They were: #define NORM(A) !!(A) #define NORM(A) ((A) != 0) I use NORM(A) in the summary to mean either substitution may be used equally well. You may choose to use NORM or "preprocess" directly. And here are the responses and some comments: #define XOR(A,B) ( !(A) && (B) || (A) && !(B) ) This was from the definition of the xor in Boolean algebra. I said this didn't work; I include it to appease those who didn't see it. Like I said, there is a way for A to be executed twice and B not at all. I also discovered a similar way to have A and B both evaluate twice. I leave that only as a challenge. It doesn't work; it fails the O&OO requirement. #define XOR(A,B) ( NORM(A) ^ NORM(B) ) This takes advantage that NORM(A) and NORM(B) are guaranteed 1 or 0. A similar macro defines: #define XOR(A,B) ( NORM(A) != NORM(B) ) Similarly, we may define: #define XOR(A,B) ( !NORM(A) ^ !NORM(B) ) since A XOR B = (NOT A) XOR (NOT B). If NORM(A) is !!(A), this is #define XOR(A,B) ( !!!(A) ^ !!!(B) ) which abbreviates to #define XOR(A,B) ( !(A) ^ !(B) ) Using != for ^ also produces the same results. #define XOR(A,B) ( (A) ? !(B) : (B) ) This does ensure B to be evaluated O&OO. In addition, it guarantees that A is executed _before_ B (if that is a factor.) It suffers: one response noted that B was substituted twice -- I don't know whether there are optimizing compilers that only generate code for B once (I don't think so, yet I cannot be sure.) One response does note correctly that this macro cannot be guaranteed (int) 0 or (int) 1, or for that matter, any int. Use in an if() of course doesn't matter, but storing the result of XOR could. That respondent does offer a solution to this problem, namely: #define XOR(A,B) ( (A) ? !(B) : NORM(B) ) That basically covers all the solutions recieved by mail and news. I thank you once again for your responses, and I leave you with the following challenge (it may be no more than a mere exercise): given: #define XOR(A,B) ( !(A)&&(B) || (A)&&!(B) ) can you use it such that A is evaluated twice and B is evaluated: no times? twice? [ Darren Morby +1 613 957 9281 {uunet|lsuc|fts1}!revcan!darren ] [ Revenue Canada Taxation, 3052-400 Cumberland St, Ottawa,ONT K1A 0L8 ] [ "Under STRANGE MAMMALS we have the platypus for $100, the sloth ] [ for $150, and for $200, Pee-Wee Herman." -Dick Clark ]