paulh@tektronix.UUCP (Paul Hoefling) (04/05/85)
I was trying to send this to Dennis Ritchie, but I can't seem to find a path to him. So, I'll open it up for net discussion (and flames :-) ). We've got a raging controversy going on here at Tektronix, and I thought that I would appeal to you for an 'official' opinion. --------------------------- The controversy: An inexperienced C programmer wrote a program containing the following: x = x++; Assuming that x originally had the value 5, what should the value be after execution of the above expression ? --------------------------- The arguments: In favor of 5: According to the operator precedence table in K&R on page 49, the ++ operator has higher precedence than the = operator. Hence the sequence of operations should be: evaluate x (value == 5) increment x (x now == 6) assign the computed value to x (x now == 5 again) In favor of 6: In K&R on page 42, the text says: "But the expression ++n increments n *before* using its value, while n++ increments n *after* its value has been used." Hence, the sequence of operations should be: evaluate x (value == 5) assign the computed value to x (x still == 5) increment x (x now == 6) --------------------------- Therefore, if the compiler writer follows the precedence table, 5 wins, and if s/he follows the text, either could win. Is there an 'official' opinion, and if so, what is it ? We are most interested in your response. I would like to point out that the various compilers around here have been tried, and we have 1 vote for 6 (our 4.2BSD compiler), and 3 votes for 5 (various microprocessor compilers). If you send mail to me at ...!tektronix!paulh, I will collect the responses and summarize for the net. If Dennis Ritchie is out there somewhere, I would *really* appreciate his opinion on the subject. -- Paul Hoefling (...!tektronix!paulh) Information Pack Rat
dad@aluxp.UUCP (DAPKUS) (04/07/85)
> We've got a raging controversy going on here at Tektronix, and I thought > that I would appeal to you for an 'official' opinion. > > An inexperienced C programmer wrote a program containing the following: > > x = x++; > > Assuming that x originally had the value 5, what should the value be after > execution of the above expression ? > ... > I would like to point out that the various compilers around here have been > tried, and we have 1 vote for 6 (our 4.2BSD compiler), and 3 votes for 5 > (various microprocessor compilers). > ... > Paul Hoefling (...!tektronix!paulh) I am fairly new to C, but by some random experimenting I witnessed a strange Phenomenon. The following program outputs a "5" on a VAX under SVR2: main () { int x; x = 5; x = x++; printf ("%d\n", x); } The active part of the generated assembly code was: movl $5,-4(fp) movl -4(fp),r0 incl -4(fp) movl r0,-4(fp) The following code on the same system outputs 6. The only difference is that x is made a register-class: main () { register int x; x = 5; x = x++; printf ("%d\n", x); } That generates: movl $5,r11 movl r11,r11 incl r11 Doesn't it seem slightly paradoxical and dangerous that using "register" in this case alters the output of the program so entirely? Also how about that redundant "movl r11,r11" generated in the register version? Donald A. Dapkus aluxp!dad
henry@utzoo.UUCP (Henry Spencer) (04/07/85)
Note that section 7 of K&R Appendix A says explicitly that the order of side effects within an expression is undefined and is up to the compiler. The ANSI C-standard drafts contain similar although more elaborate wording. The value of x after: x = 5; x = x++; is not 5 or 6, it is "5 or 6". It is most unwise to write code that relies on one particular choice. -- Henry Spencer @ U of Toronto Zoology {allegra,ihnp4,linus,decvax}!utzoo!henry
ndiamond@watdaisy.UUCP (Norman Diamond) (04/08/85)
> An inexperienced C programmer wrote a program containing the following: > > x = x++; > > Assuming that x originally had the value 5, what should the value be after > execution of the above expression ? > > In favor of 5: > According to the operator precedence table in K&R on page 49, the ++ > operator has higher precedence than the = operator. Hence the sequence of > operations should be: > evaluate x (value == 5) > increment x (x now == 6) > assign the computed value to x (x now == 5 again) > > In favor of 6: > In K&R on page 42, the text says: "But the expression ++n increments n > *before* using its value, while n++ increments n *after* its value has been > used." Hence, the sequence of operations should be: > evaluate x (value == 5) > assign the computed value to x (x still == 5) > increment x (x now == 6) The language definition doesn't say, and the construct is ambiguous (semantically ambiguous, not syntactically). Therefore all four compilers are correct (for this statement anyway) and the program is incorrect. Actually I am usually quick to catch ambiguities (roughly the same as finding counter-examples to false theorems), but never would have thought of that second interpretation. Yes the increment occurs after binding the old value, but in this particular case, even I never thought of other operations sliding in between. It's rather astounding. -- Norman Diamond UUCP: {decvax|utzoo|ihnp4|allegra}!watmath!watdaisy!ndiamond CSNET: ndiamond%watdaisy@waterloo.csnet ARPA: ndiamond%watdaisy%waterloo.csnet@csnet-relay.arpa "Opinions are those of the keyboard, and do not reflect on me or higher-ups."
carl@bdaemon.UUCP (carl) (04/09/85)
Please, let us stop this discussion of side effects right NOW. It has been beaten to death before and is pointless. Instead, read page 50 of K&R, where the following sentences can be found: "In any expression involving side effects, there can be subtle dependencies on the order in which variables taking part in the expression are stored. One unhappy situation is typified by the statement a[i] = i++; The question is whether the subscript is the old value of i or the new. The compiler can do this in different ways, and generate different answers depending on its interpretation. When side effects (assignment to actual variables) takes place is left to the discretion of the compiler, since the best order strongly depends on machine architecture. The moral of this discussion is that writing code which depends on order of evaluation is a bad programming practice in any language." Carl Brandauer daemon associates, Inc. 1760 Sunset Boulevard Boulder, CO 80302
mwm@ucbtopaz.CC.Berkeley.ARPA (04/09/85)
In article <5272@tektronix.UUCP> paulh@tektronix.UUCP (Paul Hoefling) writes: >An inexperienced C programmer wrote a program containing the following: > x = x++; >Assuming that x originally had the value 5, what should the value be after >execution of the above expression ? Either 5 or 6, depending on the phase of the moon and the mood of the compiler. That expression, like such things as: y = funct(x, x++) ; y = &x ; x = funct((*y)++) ; and other, cuter problems, are indeterminate. If you want your code to be portable, you don't use such things. C is just full of goodies like this, but so are most other languages. <mike
stew@harvard.ARPA (Stew Rubenstein) (04/10/85)
Regarding the question about x = x++ and a[i] = i++ and similarly ambiguous constructs: Why the (*@#$%^*^ can't the compiler complain rather than flipping a coin? Programs with statements like these are WRONG, just as wrong as one with a missing brace. And while I am making suggestions to the compiler-writers out there, I'd like to endorse the action of the compiler which warned the programmer of a possibly unintended assignment in the statement "if (i = 0) ..." I have spent too much time fixing bugs caused by this. I have even written "i == j;", also a legal statement, but one which I would love to have had the compiler complain about. -- ----------------------- Stew Rubenstein UUCP: ihnp4!harvard!stew Harvard Chemistry ARPA: stew@harvard
gwyn@Brl-Vld.ARPA (VLD/VMB) (04/10/85)
A more useful question might be, "What does the draft proposed ANSI C standard say about x = x++; ?" The X3J11 committee has attempted to deal with such issues by identifying what constitutes a "side effect" (post-increment is one) and when side effects must be enforced during execution (at "sequence points"). Assignment is NOT flagged as a sequence point; I don't know whether this was intentional but I suspect it was. The ";" of an expression-statement causes the expression to be evaluated for its side effects, though. The upshot is that the result is implementation-dependent. In general, one is asking for trouble any time he modifies AND uses an object in different places in the same expression, even if the behavior is supposed to be well-defined. I have yet to see a compiler that wouldn't break if pushed too hard.
moroney@jon.DEC (Mike Moroney) (04/11/85)
>An inexperienced C programmer wrote a program containing the following: > > x = x++; > >Assuming that x originally had the value 5, what should the value be after >execution of the above expression ? The VAX C compiler on VMS sure threw me with its answer to this one. I compiled and ran a test program and the answer was 5. Then I looked at the machine code, and it didn't allocate ANYTHING for x, not even a register! It generated the following code for the printf statement: pushl #5 pushal $CHAR_STRING_CONSTANTS calls #2,printf It saw through the whole mess and decided that x was 5 after the "funny" assignment operation and didn't generate any machine code for the statement "x = x++;" I tried more complex programs so the compiler would not know the value of x beforehand, and it still treated "x = x++;" as a no-op. "There's a madness to my method." Mike Moroney ..decwrl!rhea!jon!moroney
gwyn@Brl-Vld.ARPA (VLD/VMB) (04/11/85)
The compiler is perfectly within its rights in making x = 5; x = x++; result in x==5 sometimes and x==6 other times. This is one of the implementation-dependent aspects of the C language, intended to allow better overall code generation. You should not write such source code. If there is a movl r11,r11 in your output, then you must not have invoked the C optimizer (cc -O option). To make code generation easier and more reliable, the main compiler relies on the optimizer to clean up such things.
gwyn@Brl-Vld.ARPA (VLD/VMB) (04/12/85)
At least for i == j; lint issues a "null effect" message, since this is a meaningless thing for the programmer to be doing. Unfortunately if ( i = j ) is a menaingful construct that is actually widely used. I personally would have written if ( (i = j) != 0 ) but not everyone is careful to avoid the shortcuts built into C. A "boolean" data type would have been very useful for detecting such errors but C hasn't any, alas.
jack@boring.UUCP (04/12/85)
Hey, this is an old problem, and, moreover, one that exists in *every* language that allows side-effects. How about : procedure p(var i:integer):integer; begin i := i+1; p := i; end (* p *); begin j := i + p(i); end. Such constructions should *always* be avoided. -- Jack Jansen, {decvax|philabs|seismo}!mcvax!jack The shell is my oyster.
alan@drivax.UUCP (Alan Fargusson) (04/12/85)
> Regarding the question about x = x++ and a[i] = i++ and similarly > ambiguous constructs: Why the (*@#$%^*^ can't the compiler complain I didn't think that a[i] = i++ was ambiguous when I used it to set an array up shuch that each element a[i] was equal to i. So call me a hacker. The problem is that a compiler writer cannot anticipate all the errors a user might make. There are an infinite number of correct programs, and even more incorrect programs. -- Alan Fargusson. { ihnp4, sftig, amdahl, ucscc, ucbvax!unisoft }!drivax!alan
ndiamond@watdaisy.UUCP (Norman Diamond) (04/13/85)
> Regarding the question about x = x++ and a[i] = i++ and similarly > ambiguous constructs: Why the (*@#$%^*^ can't the compiler complain > rather than flipping a coin? The C compiler is perfectly capable of generating code for one of the valid meanings. (At least some compilers are. Some are capable of generating invalid code, but that's beside the point.) > Programs with statements like these are > WRONG, just as wrong as one with a missing brace. True. Is lint still occasionally maintained? Will new tests be added as their necessity becomes apparent? -- Norman Diamond UUCP: {decvax|utzoo|ihnp4|allegra}!watmath!watdaisy!ndiamond CSNET: ndiamond%watdaisy@waterloo.csnet ARPA: ndiamond%watdaisy%waterloo.csnet@csnet-relay.arpa "Opinions are those of the keyboard, and do not reflect on me or higher-ups."
lspirkov@udenva.UUCP (Goldilocks) (04/15/85)
In article <> jack@boring.UUCP (Jack Jansen) writes: > >procedure p(var i:integer):integer; >begin > p := i; > i := i+1; >end (* p *); > you obviously don't know your pascal! a function returns something. a procedure doesn't. Goldi
kjm@ut-ngp.UUCP (Ken Montgomery) (04/16/85)
[] From: lspirkov@udenva.UUCP (Goldilocks) >In article <> jack@boring.UUCP (Jack Jansen) writes: >> >>procedure p(var i:integer):integer; ^^^ >>begin >> p := i; >> i := i+1; >>end (* p *); >> > >you obviously don't know your pascal! a function returns >something. a procedure doesn't. > > Goldi The 'var' keyword has the effect that the value of 'i' is assigned to the corresponding actual parameter in the calling routine at the termination of the called routine. -- The above viewpoints are mine. They are unrelated to those of anyone else, including my cats and my employer. Ken Montgomery "Shredder-of-hapless-smurfs" ...!{ihnp4,allegra,seismo!ut-sally}!ut-ngp!kjm [Usenet, when working] kjm@ut-ngp.ARPA [for Arpanauts only]
john@moncol.UUCP (John Ruschmeyer) (04/18/85)
>From: kjm@ut-ngp.UUCP (Ken Montgomery) >Message-ID: <1617@ut-ngp.UUCP> > >From: lspirkov@udenva.UUCP (Goldilocks) >>In article <> jack@boring.UUCP (Jack Jansen) writes: >>> >>>procedure p(var i:integer):integer; > ^^^ >>>begin >>> p := i; >>> i := i+1; >>>end (* p *); >>> >> >>you obviously don't know your pascal! a function returns >>something. a procedure doesn't. >> >> Goldi > >The 'var' keyword has the effect that the value of 'i' is assigned >to the corresponding actual parameter in the calling routine at the >termination of the called routine. What goldi was referring to was this: >procedure p(var i:integer):integer; ^^^^^^^^ The part I have highlighted is used in a FUNCTION declaration to declare the type of the value returned. The type of values returned by a PROCEDURE is declared by the 'var' as you pointed out. The correct declaration is: procedure p(var i:integer); I don't have the original article handy, but it almost looks like someone was trying to perform the illegal: function p(var i:integer):integer; which would be an attempt at declaring a function which returns two values. I pray that somewhere there isn't a compiler which would accept that. (Ooh, ick!) -- Name: John Ruschmeyer US Mail: Monmouth College, W. Long Branch, NJ 07764 Phone: (201) 222-6600 x366 UUCP: ...!vax135!petsd!moncol!john ...!princeton!moncol!john ...!pesnta!moncol!john Silly Quote: "Ah, but what is a dream but reality without a backbone?"
lspirkov@udenva.UUCP (Goldilocks) (04/19/85)
In article <> kjm@ut-ngp.UUCP (Ken Montgomery) writes: >[] > >From: lspirkov@udenva.UUCP (Goldilocks) >>In article <> jack@boring.UUCP (Jack Jansen) writes: >>> >>>procedure p(var i:integer):integer; > ^^^ >>>begin >>> p := i; >>> i := i+1; >>>end (* p *); >>> >> >>you obviously don't know your pascal! a function returns >>something. a procedure doesn't. >> >> Goldi > >The 'var' keyword has the effect that the value of 'i' is assigned >to the corresponding actual parameter in the calling routine at the >termination of the called routine. > >Ken Montgomery "Shredder-of-hapless-smurfs" I wasn't talking about the var parameters. i was talking about his syntax. try running that bit of code (with a main program & the rest of the skeleton) and see what you get... Goldi ps: what it should have been was: function p(var i:integer):integer; ^^^^^^^^ ... pps: i got mail from someone at harvard but i couldn't reply straight to him. so this is just for him: you're right. i don't know my modula-2. i never claimed i did. but he specifically said pascal.
robert@gitpyr.UUCP (Robert Viduya) (04/19/85)
> > I don't have the original article handy, but it almost looks like someone > was trying to perform the illegal: > > function p(var i:integer):integer; > > which would be an attempt at declaring a function which returns two values. > I pray that somewhere there isn't a compiler which would accept that. > (Ooh, ick!) > Wait a minute... Pascal allows you to have var parameters in functions. There is nothing illegal about the declaration whatsoever. All the Pascal compilers I've used accept this. And what's wrong with functions modifying their parameters? robert -- Robert Viduya Georgia Institute of Technology ...!{akgua,allegra,amd,hplabs,ihnp4,masscomp,ut-ngp}!gatech!gitpyr!robert ...!{rlgvax,sb1,uf-cgrl,unmvax,ut-sally}!gatech!gitpyr!robert
tainter@gumby.UUCP (04/22/85)
> I don't have the original article handy, but it almost looks like someone > was trying to perform the illegal: > > function p(var i:integer):integer; > > which would be an attempt at declaring a function which returns two values. > I pray that somewhere there isn't a compiler which would accept that. > (Ooh, ick!) > Say what? It is completely legal in Pascal to pass var parameters to a function! I PRAY all pascal compilers out there will accept this!! -Johnathan A. Tainter -- The views expressed are those of GOD and do not reflect on the author.
bprice@bmcg.UUCP (Bill Price) (04/26/85)
> > I don't have the original article handy, but it almost looks like someone > > was trying to perform the illegal: > > function p(var i:integer):integer; > > I pray that somewhere there isn't a compiler which would accept that. > > (Ooh, ick!) > Say what? It is completely legal in Pascal to pass var parameters to a > function! I PRAY all pascal compilers out there will accept this!! > -Johnathan A. Tainter ANSI, IEEE, ISO, and others have published the definition of Pascal: it's titled, for example, "American National Standard Pascal Computer Programming Language." According to this definition, one of the requirements of a Pascal compiler is that it accepts the Pascal language--that's so obvious that it's often overlooked. One of the features of the Pascal language is the ability of a function to have variable parameters. The bottom line of that paragraph is the trivial conclusion that: A compiler which does not accept a function declaration with a variable parameter is not a Pascal compiler, regardless of the name of the compiler, and regardless of any claims by the compiler writer or vendor. "How many legs does a donkey have if you call its tail a leg?" "One--calling a tail a leg doesn't make it one." --A. Lincoln --Bill Price -- --Bill Price uucp: {Most Anybody}!sdcsvax!bmcg!bprice arpa:? sdcsvax!bmcg!bprice@nosc
fjh@cord.UUCP (07/16/86)
What is the difference between: extern char *A; and extern char A[]; If you do: printf("A=%s\n",A); the first causes a core dump, the second works. I thought pointers and arrays were equivalent? ----- Please send me mail, if you understand this. Thanks! -- <*> Fred Hirsch <*> AT&T Bell Laboratories <*> ihnp4!cord!fjh <*>
chris@umcp-cs.UUCP (07/17/86)
In article <306@cord.UUCP> fjh@cord.UUCP (FJ Hirsch) writes: >What is the difference between: > >extern char *A; > >and > >extern char A[]; Quite a bit. The former tells the compiler that there is a variable named `A' defined externally, and that its type is `pointer to char'. The latter tells it that there is a variable named `A' defined externally, and that its type is `array of char'. These are most certainly *not* equivalent. A Vax compiler, for example, treats the former as a four-byte variable, and the latter as a `link-time constant'. >If you do: printf("A=%s\n",A); >the first causes a core dump, the second works. In that case, the actual defintion must have been char A[<constant>]; >I thought pointers and arrays were equivalent? No. This confusion seems to arise from C's convention of treating the name of an array (in many places, but not all) as a pointer to the first element of that array. It is heightened by C's convention of allowing an `array' declaration as a formal parameter: f(s) char s[]; { ... It might have been better if compilers refused to accept such a declaration, rather than silently altering it to read char *s; So when *is* an object of type `array of <stuff>' treated as an object of type `pointer to <stuff>'? If I have not forgotten anything, the answer is `everywhere except in sizeof and in actual declarations'. `extern char *A' and `extern char A[]' are actual (not formal) declarations. -- In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 1516) UUCP: seismo!umcp-cs!chris CSNet: chris@umcp-cs ARPA: chris@mimsy.umd.edu