chip@tct.uucp (Chip Salzenberg) (08/28/90)
According to cbp@icc.com (Chris Preston): > For instance, I am told that the following is a problem in Kanji > > char p[10]; /* xscc provides for allowing twenty bytes as needed in Kanji */ > > *(p+1)='x'; /* this is the next byte, and an error */ > p[n+1]='x'; /* this is the next _character_ and ok */ Just so no one panics: Unless I misunderstand Chris Preston's example, this bit of code is not a harbinger of things to come, but rather an artifact of a broken compiler. Any compiler that considers "*(p+1)" and "p[1]" to be different does not comply with the ANSI standard -- or with K&R, for that matter. Since time immemorial, "*(a+b)" and "a[b]" have been synonymous, and such is C today. -- Chip Salzenberg at Teltronics/TCT <chip@tct.uucp>, <uunet!pdn!tct!chip>
prs@io.UUCP (Paul Schmidt) (08/30/90)
In article <26D952F5.4E44@tct.uucp> chip@tct.uucp (Chip Salzenberg) writes: > >Any compiler that considers "*(p+1)" and "p[1]" to be different does >not comply with the ANSI standard -- or with K&R, for that matter. So, that means that the compiler must know the size of the elements of array p, and that *(p+1) does not add 1 to p, but instead adds sizeof(array_element_type) to p? I must confess that I use p[1] in these cases, and count on the compiler to optimize for me.
henry@zoo.toronto.edu (Henry Spencer) (08/31/90)
In article <1745@io.UUCP> prs@eng.ileaf.com (Paul Schmidt) writes: >>Any compiler that considers "*(p+1)" and "p[1]" to be different does >>not comply with the ANSI standard -- or with K&R, for that matter. > >So, that means that the compiler must know the size of the elements of >array p, and that *(p+1) does not add 1 to p, but instead adds >sizeof(array_element_type) to p? Although you phrased it a bit poorly, that is correct. What is the *meaning* of adding 1 to a pointer? In C, it means that the pointer is increased as far as necessary to point to the next array element. What happens to the actual bit patterns is the compiler's business; typically this will, indeed, involve adding sizeof(*p) to p, considered as an integer. >I must confess that I use p[1] in these cases, and count on the compiler >to optimize for me. Ignoring some syntactic nit-picking, p[1] is *identical* to *(p+1), by definition of the C subscripting operation. -- TCP/IP: handling tomorrow's loads today| Henry Spencer at U of Toronto Zoology OSI: handling yesterday's loads someday| henry@zoo.toronto.edu utzoo!henry
bruce@seismo.gps.caltech.edu (Bruce Worden) (09/01/90)
In article <1745@io.UUCP> prs@eng.ileaf.com (Paul Schmidt) writes: > [ material deleted ] >So, that means that the compiler must know the size of the elements of >array p, and that *(p+1) does not add 1 to p, but instead adds >sizeof(array_element_type) to p? Yes. It is very important to understand that point if you are going to be shuffling pointers around. >I must confess that I use p[1] in these cases, and count on the compiler >to optimize for me. In a simple case like p[1] the compiler may well optimize, but then it isn't a particularly time consuming operation. Though we are getting bit off of the original subject, in the case of a loop, the performance difference between *p1++ = *a1++ * *b1++; and p2[i] = a2[i] * b2[i]; can be significant. The performance strongly depends on the compiler and, in the case of floating-point operands, how well the compiler exploits the features available in the hardware. -------------------------------------------------------------------------- C. Bruce Worden bruce@seismo.gps.caltech.edu 252-21 Seismological Laboratory, Caltech, Pasadena, CA 91125
brnstnd@kramden.acf.nyu.edu (Dan Bernstein) (09/01/90)
In article <1990Aug31.190103.15043@laguna.ccsf.caltech.edu> bruce@seismo.gps.caltech.edu (Bruce Worden) writes: > In article <1745@io.UUCP> prs@eng.ileaf.com (Paul Schmidt) writes: > >I must confess that I use p[1] in these cases, and count on the compiler > >to optimize for me. > In a simple case like p[1] the compiler may well optimize, but then it isn't > a particularly time consuming operation. Huh? p[1] means exactly the same thing as *(p+1). At least two compilers here (neither pcc-based) do that translation as the very first step. There's no ``optimization'' involved. > *p1++ = *a1++ * *b1++; > p2[i] = a2[i] * b2[i]; Note that on vector machines the latter is much faster in a loop. ---Dan
bruce@seismo.gps.caltech.edu (Bruce Worden) (09/01/90)
In article <29605:Aug3120:51:0290@kramden.acf.nyu.edu> brnstnd@kramden.acf.nyu.edu (Dan Bernstein) writes: >Huh? p[1] means exactly the same thing as *(p+1). At least two compilers >here (neither pcc-based) do that translation as the very first step. >There's no ``optimization'' involved. It is really an extremely small point. As far as I know, nothing specifies that the code generated by the two statements has to be identical, only that the results are the same. One could imagine a compiler that did one less efficiently than the other. >> *p1++ = *a1++ * *b1++; >> p2[i] = a2[i] * b2[i]; >Note that on vector machines the latter is much faster in a loop. My point exactly. Except that the example you give isn't necessarily true. On our Convex both will vectorize, and the run time is the same. -------------------------------------------------------------------------- C. Bruce Worden bruce@seismo.gps.caltech.edu 252-21 Seismological Laboratory, Caltech, Pasadena, CA 91125
throopw@sheol.UUCP (Wayne Throop) (09/02/90)
> From: bruce@seismo.gps.caltech.edu (Bruce Worden) >> (Paul Schmidt) >> *(p+1) does not add 1 to p, but instead adds >> sizeof(array_element_type) to p? > Yes. No. Or less bluntly, that's not (IMHO) a very good way of putting it. Bruce is right as far as he goes, but I think Paul's phrase above is misleading. What I'm objecting to is the dimensionless "adding one to it (a pointer)". One what? People most probably mean "one byte" by this, but I don't think peoples' understanding of pointer arithmetic is strong enough to trust their notions of "add one to" a pointer should be trusted. And I think history bears me out. Or to be specific, I druther see the above exchange be something like Q. *(p+1) does not add 1 to p, but instead adds sizeof(array_element_type) to p? A. No. It produces a pointer value that references the next array_element_type array element after the one referenced by p. On byte addressed machines, the bit pattern of this pointer, when treated as an integer, is often an integer sizeof(array_element_type) greater than the integer gotten by treating the bits of p as an integer. But this latter fact is a coincidence produced by a particular implementation of C pointers. Now, I suppose this seems awfully picky. "Didn't he just say that" and all that. But the point is that the underlying assumption of a smooth byte-granular address space with pointers represented as integer offsets into this address space is NOT the best way of explaining pointers, even if it is the one so many people use. Or to try putting it another way, I think it is misleading to say that "adding one to p 'really' adds sizeof(*p) to p". I disagree. I say it "really" adds 1, and the result points at an element in the array into which p points which is offset exactly 1 array element from where p points. -- Wayne Throop <backbone>!mcnc!rti!sheol!throopw or sheol!throopw@rti.rti.org
steve@groucho.ucar.edu (Steve Emmerson) (09/03/90)
In <0901@sheol.UUCP> throopw@sheol.UUCP (Wayne Throop) writes: >Or to try putting it another way, I think it is misleading to say that >"adding one to p 'really' adds sizeof(*p) to p". I disagree. I say it >"really" adds 1, and the result points at an element in the array into >which p points which is offset exactly 1 array element from where p >points. Isn't the point moot if a conforming program can't tell the difference? Steve Emmerson steve@unidata.ucar.edu ...!ncar!unidata!steve
throopw@sheol.UUCP (Wayne Throop) (09/03/90)
> From: steve@groucho.ucar.edu (Steve Emmerson) >> [...] it is misleading to say that "adding one to p 'really' adds >> sizeof(*p) to p". [...] it "really" adds 1, and the result points at an >> element [...] which is offset exactly 1 array element [...] > Isn't the point moot if a conforming program can't tell the difference? In terms of correctness, I agree (once one fills in the implied information that one is assuming integer arithmetic on byte offset pointers). But my point wasn't directed at correctness, but at communication. So I'd say the point is moot only if the difference in phrasing doesn't mislead programmers into producing nonconforming programs. And I think it pretty clear that this particular issue misleads more people than many another, and that extreme care in communication is warranted. Then again, maybe I'm just too picky... but I still don't think so. -- Wayne Throop <backbone>!mcnc!rti!sheol!throopw or sheol!throopw@rti.rti.org
hunter@Oswego.EDU (Eric Hunter) (09/04/90)
In <0901@sheol.UUCP> throopw@sheol.UUCP (Wayne Throop) writes: >Or to try putting it another way, I think it is misleading to say that >"adding one to p 'really' adds sizeof(*p) to p". I disagree. I say it >"really" adds 1, and the result points at an element in the array into >which p points which is offset exactly 1 array element from where p points. It doesn't "really" add 1; it increments the pointer variable to the next available address. Eric. ------------------------------------------------------------------------------- | Eric Hunter | The difference between emacs, and vi, is like the| | hunter@oswego.oswego.edu | difference between making love, and masturbation.| -------------------------------------------------------------------------------
martin@mwtech.UUCP (Martin Weitzel) (09/04/90)
In article <1990Aug31.163647.11121@zoo.toronto.edu> henry@zoo.toronto.edu (Henry Spencer) writes: >In article <1745@io.UUCP> prs@eng.ileaf.com (Paul Schmidt) writes: [...] >>So, that means that the compiler must know the size of the elements of >>array p, and that *(p+1) does not add 1 to p, but instead adds >>sizeof(array_element_type) to p? [...] >Ignoring some syntactic nit-picking, p[1] is *identical* to *(p+1), by >definition of the C subscripting operation. And in all flavours of UNIX I've ever used there is a compiler option (usually -S) which leaves an assembly language file (usually suffixed .s) and I've never seen a difference in the assembly source for both constructs But note: The fact that *(p+1) can be interchanged with p[1] (and even with 1[p]) does of course NOT mean that there is no difference between pointers and arrays. With: T a[10], *ap = a; the machine code produced for a[1] is DIFFERENT from the code for *(ap+1); but the latter is the same as for ap[1] and the former is the same as for *(a+1). -- Martin Weitzel, email: martin@mwtech.UUCP, voice: 49-(0)6151-6 56 83
mat@mole-end.UUCP (Mark A Terribile) (09/04/90)
In article <1745@io.UUCP>, prs@io.UUCP (Paul Schmidt) writes: > In article <26D952F5.4E44@tct.uucp> chip@tct.uucp (Chip Salzenberg) writes: > > > >Any compiler that considers "*(p+1)" and "p[1]" to be different does > >not comply with the ANSI standard -- or with K&R, for that matter. > So, that means that the compiler must know the size of the elements of > array p, and that *(p+1) does not add 1 to p, but instead adds > sizeof(array_element_type) to p? What's the problem? The compiler needs to know the length anyway. And yes, the pointer is adjusted by the length of the object at which it (is presumed to) point. > I must confess that I use p[1] in these cases, and count on the compiler > to optimize for me. What does optimization have to do with anything? The compiler can generate the same code for both expressions. Because C gives the programmer so much addressing control and because aliasing can occur, the compiler cannot always do strength reductions. The equivalence of p[ i ] and *( p + i ) is at the very heart of the C language definition. If you are programming in C, you CAN rely upon it, not by some coincidence or compiler peculiarity, but in the most portable way of all, by the actual definition of the language. If the compiler writer cannot implement this behavior well, he cannot implement C well on that machine. -- (This man's opinions are his own.) From mole-end Mark Terribile
throopw@sheol.UUCP (Wayne Throop) (09/10/90)
>> throopw@sheol.UUCP >>I think it is misleading to say that "adding one to p 'really' adds >>sizeof(*p) to p". [...] I say it "really" adds 1, and the result [...] >>points at an element [...] offset exactly 1 > From: hunter@Oswego.EDU (Eric Hunter) > It doesn't "really" add 1; it increments the pointer variable to the next > available address. Which, I still claim, is "really" adding one. My argument was against assuming that the integer representation of pointers was to indicate a byte offset. This is not true for some current machines, and is at best a misleading way of thinking about the situation. "The next available address" may well NOT be "sizeof element" architectural units away from the address one starts with. Or it may well be exactly one unit away, for element type of short, or int, or even double. I think it is a bad idea to explain abstract things in terms of a concrete implementation in other than examples. -- Wayne Throop <backbone>!mcnc!rti!sheol!throopw or sheol!throopw@rti.rti.org