TITLE: Question about "intelligent" use of ?: construct PROBLEM: Ken M. (martinka@benji.Colorado.EDU) I hope that this question is not in some FAQ somewhere. If it is, please mail me a ftp location where I could get the FAQ. Hopefully this is a Worthy question. I converting some old dos code to windows but am having some trouble understanding an algorithm using the ?: opperator. I am having trouble finding decent documentation on using this operator. Here is the line that uses the opperator: double dA; double dB; double Basis; dA=.....; Basis=......; dB = ((dA <=1) ? 1: (dA <= 2) ? 2: (dA <=5) ? 5: (Basis*= 10,1)) * Basis; That is it! Unfortunatly, the only commenting in this algorithm was that it was "intelligent." If some one could decipher what this does could you send me the psudocode or the if then statements that this translates to. RESPONSE: hhakkine@cs.joensuu.fi (H{k{ H{kkinen) I don't love that kind of code. Either I'm not so intelligent or they are not .. even though the compiler can make it faster that way. IF I understand correctly, this would be similar to if ( dA <= 1 ) help = 1 ; else if ( dA <= 2 ) help = 2 ; else if ( dA <= 5 ) help = 5 ; else help = ( Basis *= 10,1 ) ; dB = help * Basis ; But even here I wonder that 10,1 ... could it be 10.1 ?? If I understood this wrong, would someone please tell the truth ? RESPONSE: torek@elf.bsdi.com (Chris Torek), 19 Aug 94 In article <330e9n$mpt@shadow.eng.pyramid.com> moliver@pyramid.com (Mike Oliver) notes that the expression: dB = ((dA <=1) ? 1: (dA <= 2) ? 2: (dA <=5) ? 5: (Basis*= 10,1)) * Basis; is undefined, because it both uses and modifies `Basis' without an intervening sequence point (and the `use' is not in determining the new value). In article Arjan Kenter suggests that it is defined after all: >If it wasn't for the comma operator of course. Remember it introduces a >sequence point. Although the comma operator *does* impose a sequence point, this particular sequence point does not occur `between' the two uses of Basis. This sequence point imposes only a partial order: we know that `Basis *= 10' must be complete before evaluating the second expression (`1'). We do not know whether this occurs before, during, or after the evaluation of the other `Basis', however. (A compiler could, for instance, compile the above for a stack machine as: push Basis multiply push &dB store which would use the previous Basis, not the new tenfold Basis.) Suppose we have the following: int x, f(void), g(void), h(void), i(void); x = (f(), g()) + (h(), i()); Now imagine that f(), g(), h(), and i() look like this: int f(void) { puts("f"); return 0; } int g(void) { puts("g"); return 1; } int h(void) { puts("h"); return 2; } int i(void) { puts("i"); return 3; } The variable `x' will definitely be set to 4, because g() returns 1 and i() returns 3 and the expression `(f(), g()) + (h(), i())' adds the values returned from g() and i(). The order of the four lines of output, however, is unspecified[%], except that we know that `f' must print before `g', and `h' must print before `i'. This gives us six possible orders of evaluation: f, g, h, i [do everything left to right] h, i, f, g [do right to left except as forced] f, h, g, i [do f and h, then add g+i] h, f, i, g [etc] f, h, i, g h, f, g, i ----- [%] There was some nonsense about interleaving the statements in f and h---on a multiprocessor, we might fork and do them both in parallel---which the Standard does not literally prohibit. Such an implementation would prove unmanageable, however, if the compiler did not first guarantee that this sort of parallel evaluation still *appeared* sequential. A trivial example occurs if we make f and h each print two identical characters with putchar(): if the output is not `ffhh' or `hhff', but rather is `fhfh' or `hfhf', we could predict that most nontrivial programs would behave erratically in this system. ----- Incidentally, the original expression: dB = ((dA <=1) ? 1: (dA <= 2) ? 2: (dA <=5) ? 5: (Basis*= 10,1)) * Basis; is a classic example of the mistaken belief that shorter is always better. (This code is probably selecting alternatives for displaying a graph, or doing something similar with powers of 10 for human consumption. It also makes me wonder what happens if dA > 20.) Shorter is better when it avoids unnecessary complexity. When, as in this case, it *adds* complexity, well....