mcewan (02/27/83)
#R:houxj:-22000:uiucdcs:27600008:000:271 uiucdcs!mcewan Feb 26 21:47:00 1983 i = 4; i = i++; printf ("%d\n", i); ---------- Clearly, the value of "i++" is 4. However, c does not specify whether the increment or the assignment is done first, so the value of i after this statment is UNDEFINED, or, if you prefer, "compiler dependent".
johnl (02/27/83)
#R:houxj:-22000:ima:15900002:000:735 ima!johnl Feb 26 12:53:00 1983 Re: table[i++] = ++i; The term "expression" in K&R refers to the entire expression (remembering that = is syntactically just an operator.) Ergo, the compiler can legitimately fool with both of the ++ operators. If there's ever going to be an ANSI C standard, we'll have to straighten this sort of thing out. A while ago I posed a similar problem: a = foo(i++); asking whether the ++ has to be done before foo() is called. Strictly, K&R doesn't appear to require it, but in practice many programs assume that it is, so real compilers usually do so. (And please don't send out your opinion on the right thing to do; we beat this dead horse already.) John Levine, decvax!yale-co!jrl, ucbvax!cbosgd!ima!johnl, research!ima!johnl
preece (03/01/83)
#R:houxj:-22000:uicsl:6400003:000:475 uicsl!preece Feb 28 12:42:00 1983 I just noticed that my remarks are really aimed at a response to the base note (which itself mentionend pg50 of K&R). Sorry. I think my response to the base note (which looked at the expression table[i++]=i++ and asked if the compiler was allowed to evaluate part of one expression, then part of another, then the rest of the first, then the rest of the second) is that the whole thing is one expression, not two, and therefore can be evaluated in any order. scott preece
alb (03/03/83)
i = 4; i = i++; Regardless of whether the increment of the assignment comes first, i == 5 afterwards. Think: If the increment comes first: i++ (so i == 5) i = i (so i == 5) If the assignment comes first: i = i (so i == 4) i++ (so i == 5)
dmmartindale (03/09/83)
It isn't necessarily true that i == 5 after executing i = 4; i = i++; Consider the following code sequence for i=i++ on a hypothetical machine: lda i # load i into accumulator aos i # do post-increment with Add One to Storage instruction sta i # and then store back into i At the end, i == 4. This is a perfectly reasonable code sequence to generate on a machine that has no two-operand instructions, but does have an "aos" instruction. Moral: Never try to second-guess the compiler and hardware when the result is not defined by the semantics of the language. Dave Martindale
wagner (03/10/83)
We seem to be confusing several different things all into one big basket here. There are several cases when C is allowed to re-arrange things, and we seem to be lumping some of them together. First off: 1) In a private communication, Dave Martindale told me (I hope he doesnt mind me quoting him "on the air" that the expression foo(++i,++i) could pass 3 different sets of parameters to foo; i.e., if i was zero before we started, foo could get passed 1,2 2,1 or 2,2 and the decision was up to the compiler. The relevant quote here is "The order of evaluation of arguements [to functions] is undefined by the language; take note that the various compilers differ". In talking with others around here, it seems the issue boils down to whether the increment/decrement operators are indivisible or not. I suspect that there is room for a fourth option; foo could get passed 1,1 if each subexpression first picked up the current value of i into a different private register, then each private register was incremented, then each was stored back into the memory location for i, then the value was passed to foo. The order of evaluation of arguments is undefined... but are we guaranteed that all of one is finished before another starts, or are we open to "race" conditions? This may well become important when multiprocessors become more popular. 2) Someone in news today said that the sequence i=4; i=i++; would always equal 5; this I believe to be incorrect. The action of i++ is a) copy the value of i to a safe place b) increment i c) the result of the subexpression i++ is the value in the safe place. Point (c) above implies that the result assigned to i would be 4. In the case i=++i, i is (almost) trivially 5, since the expression simplifies to i=i+1, with little chance for confusion. 3) Several people have said that C expressions may be rearranged arbitrarily; that is not true. There are still rules of precedence and so on. Subexpressions may be computed in any order, even in the face of side effects, and the order of operands to binary *, +, &, | and ^ can be shuffled. This is all very fascinating, and I have spent several hours going through K&R to try to sort all this out, but I think anyone who relied on any of these things, even in a language which claimed to have more rigidly defined order of evaluation, would be coming up with code which was unreadable by a human, even if the compiler did promise to sort it out. Michael Wagner, UTCS
msc (03/10/83)
I have listened to the discussion about the order of evaluation of expressions and the areas which can vary from compiler to compiler. There is a very entertaining little book whose intention is to point up these and other fun areas of C. It is called "The C Puzzle Book" Alan R. Feuer Prentice-Hall, Englewood, N.J., 1982 I recommend it highly to anyone who is investigating some of the intricacies of C and to anyone who likes brain-teasers. Mark Callow Qubix Graphic Systems ...decvax!decwrl!qubix!msc ...ucbvax!ucscc!qubix!msc
preece (03/12/83)
#R:houxj:-22000:uicsl:6400004:000:1052 uicsl!preece Mar 11 08:28:00 1983 ***** uicsl:net.lang.c / alice!e / 3:46 pm Mar 3, 1983 i = 4; i = i++; Regardless of whether the increment of the assignment comes first, i == 5 afterwards. Think: If the increment comes first: i++ (so i == 5) i = i (so i == 5) If the assignment comes first: i = i (so i == 4) i++ (so i == 5) --------- Think again: Stack old value of i Store incremented value in i Pop stacked (old) value into i (so i == 4) This is a perfectly reasonable interpretation, given that the whole line (i = i++) is one expression, and therefore re-arrangeable. In fact, many would say it's the RIGHT way, since it means the result of 'a = i++' and 'i = i++' are the same. Clearly K+R says they're all right methods, and the author should avoid ambiguous expressions. [I agree with most of you out there that this topic has had enough attention, but i also think it's worthwhile to keep addressing mis-interpretations in the hopes of as many readers as possible understanding the problem and avoiding such usage.] scott e preece uiuc coordinated science lab
preece (03/13/83)
#R:houxj:-22000:uicsl:6400005:000:1091 uicsl!preece Mar 12 14:31:00 1983 No. Sorry, but I think mine is a reasonable human interpretation and, in fact, that's the way I'd like the computer to be required to reach (that is, i'd really like the assignment operator to force its right side to finish up before assigning). My argument is as given before: a = i++ and i = i++ really ought to result in their left-hand sides being the same. That's an argument from human interpretation, not machine internals. I suspect it's also compatible with the original machine purpose of the ++ form, which was to take advantage of special pdp-11 addressing mode that increments after fetching the contents of a register; thus they were intended to leave the incremented value in the variable immediately after obtaining the old value, not at the end of expression evalutation. The book is clear - the implementor can do it any way convenient. And anyone writing the line of code i = i++ deserves to not know exactly what's going to come out. And anyone writing C code should be aware that order of evaluation is not controllable. scott e preece uiuc coordinated science lab
donchin (03/14/83)
#R:houxj:-22000:uiucdcs:27600012:000:460 uiucdcs!donchin Mar 11 21:56:00 1983 The rethinking in the last note is of an entirely different form from the thoughts in the response it addressed. The original argument (that the resulting value for i should be 5) was looking at the question from a high level point of view. He was showing that the two reasonable human interpretations for the expression both yeild the same result, and the computer interpretation should be made to conform. Regardless of how the computer works internally.
mark (03/16/83)
#R:houxj:-22000:zinfandel:14600004:000:1416 zinfandel!mark Mar 10 11:28:00 1983 Michael Wagner has a very good point: readability by humans. When I run across like that being discussed here I have to decide: 1. How does this code work on the machine for which the author wrote it? 2. How does it work on the machine(s) on which I intend to run it? 3. If they are different does it matter? 4. If it matters, is it a. necessary (eg, fix differences in the machines) b. a "feature" (ie, can be tolerated) c. a "bug" (ie, must be fixed) 5. Did the author consider any or all of (1)-(5)? 6. If so, do I think s/he was correct on all of them? 7. If not, am I missing something or is the author? 8. If the author didn't consider all of the points, or was wrong on some of them, how closely should I look at the rest of the code for other non-portable constructs? In other words, even if the code works probably on all existing and known machines and compilers I have to waste a lot of time on the code, even if it turns out to be ok. I don't care if the compiler can sort things out if people can't; such features should be used, even when portable, without a very compelling reason. Mark Wittenberg ...!decvax!sytek!zehntel!mark PS. I can't think of any compelling reasons for the examples mentioned here. PPS. I also don't like use of ADA overloading for similar reasons; please direct all flames to /dev/null, as I don't want to start ADA debates here.