ok@quintus.UUCP (Richard A. O'Keefe) (12/19/87)
According to the UNIX System V Programmer's Guide, 1987 paperback edition, page 740: The expression E1[E2] is identical (by definition) to *((E1)+(E2)). The October 86 draft of the ANSI C standard said (Rationale section 3.3.2.1) The Committee found no reason to disallow the symmetry that permits a[i] to be written as i[a]. and in the standard proper The definition ... is that E1[E2] is identical to (*(E1+(E2))). [The two definitions are equivalent.] What we're getting at here is that if you want to represent positions in 3D space, a good dodge is to write #define x_of(V) 0[V] #define y_of(V) 1[V] #define z_of(V) 2[V] Notice that there are no superfluous parentheses, that this notation can be read directly as "2nd element of V", and that this has always been explicitly legal in C. Some versions of the Green Hills C compiler for MC680x0 do not accept this syntax. There may be other versions which do accept it. There may be other compilers with this error: the VAX-11 C manual for VMS says "addr[intexp]" which suggests that it MAY have the same mistake. BTW: now that the ANSI C committee have decided to flout centuries of mathematical tradition and make (X+Y) different from X+Y, what does this do to E1[E2]? [The two definitions above are NOT equivalent if parentheses act as in FORTRAN. This is a good reason why parentheses should have their usual mathematical meaning: straightforward reasoning about a program can go seriously wrong if parentheses act so strangely.]
gwyn@brl-smoke.ARPA (Doug Gwyn ) (12/20/87)
In article <482@cresswell.quintus.UUCP> ok@quintus.UUCP (Richard A. O'Keefe) writes: >BTW: now that the ANSI C committee have decided to flout centuries >of mathematical tradition and make (X+Y) different from X+Y, what >does this do to E1[E2]? First of all, you appear to be under some misunderstanding. (X+Y) is no more different from X+Y under the new rule than it ever was. The only "flouting of mathematical tradition" is that done by the hardware, which instead of working with abstract mathematical symbols uses imperfect representations of numeric values. Overflow and loss of precision were by no means invented by X3J11; we just had to figure out how to cope with them. The meaning of E1[E2] is unaffected by the new non-regrouping rule. It is still equivalent to E2[E1]. It is certainly true, as you said, that straightforward reasoning about a program can go seriously wrong, but not for the reason you stated. The real problem is that, although program source notation resembles mathematical notation, it is NOT the same thing and does NOT have the same properties. Assumptions to the contrary are what leads one astray. There are methodologies for correct reasoning about programs; the names Dijkstra and Hoare come to mind.
ok@quintus.UUCP (Richard A. O'Keefe) (12/21/87)
In article <6883@brl-smoke.ARPA>, gwyn@brl-smoke.ARPA (Doug Gwyn ) writes: > In article <482@cresswell.quintus.UUCP> [I wrote]: > >BTW: now that the ANSI C committee have decided to flout centuries > >of mathematical tradition and make (X+Y) different from X+Y, what > >does this do to E1[E2]? > > First of all, you appear to be under some misunderstanding. > (X+Y) is no more different from X+Y under the new rule than it ever was. Under the new rules, (X+Y) and X+Y are in fact different, that is, they BEHAVE differently. (X and Y stand for arbitrary expressions.) The point here is that E1[E2] has in the past been defined in one of two previously equivalent ways: (*((E1)+(E2))) or (*(E1+(E2))) If parentheses have an operational effect, these two definitions are no longer equivalent. What I was asking for, and still would like, is a plain statement of what the new definition of E1[E2] is, and in particular, a plain statement of under which conditions the compiler is entitled to merge E1 and E2 rather than evaluating them separately. (Note that this is POINTER arithmetic, >>not<< integer arithmetic, so statements about equivalence if integer overflow is disabled are not enough to tell me whether the compiler is entitled to treat 2[a+1] as a[3] or not.) Surely this isn't too much to ask?
gwyn@brl-smoke.ARPA (Doug Gwyn ) (12/21/87)
In article <484@cresswell.quintus.UUCP> ok@quintus.UUCP (Richard A. O'Keefe) writes: >Under the new rules, (X+Y) and X+Y are in fact different, that is, >they BEHAVE differently. No, they don't, unless the expressions X and Y contain operators that bind more tightly that + and "X+Y" is imbedded in a context where that matters. >The point here is that E1[E2] has in the past been defined in one of >two previously equivalent ways: > (*((E1)+(E2))) >or (*(E1+(E2))) >If parentheses have an operational effect, these two definitions are >no longer equivalent. Parentheses have the same effect they have always had in C, namely they can be used to override default operator associativity and precedence. The only change brought on by the latest X3J11 meeting is that compilers are no longer free to run rampant when optimizing expressions involving nominally commutative+associative operators. >What I was asking for, and still would like, is >a plain statement of what the new definition of E1[E2] is, The first one you quoted is probably the best form to use, since E1 may contain some operator that binds more weakly than +. >statements about equivalence if integer overflow is disabled are not >enough to tell me whether the compiler is entitled to treat >2[a+1] as a[3] or not. 2[a+1] is equivalent to *(2+(a+1)). Assuming that a through a+3 are all meaningful addresses, then this is indeed equivalent to a[3].